← Home
```go
package main

import (
	"fmt"
)

var divisors []int
var lcmToIdx map[int]int
var nextLcm [10][48]int
var isValid [2520][48]bool
var numDiv int

func gcd(a, b int) int {
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

func lcm(a, b int) int {
	return a / gcd(a, b) * b
}

func init() {
	for i := 1; i <= 2520; i++ {
		if 2520%i == 0 {
			divisors = append(divisors, i)
		}
	}
	numDiv = len(divisors)
	lcmToIdx = make(map[int]int, numDiv)
	for idx, v := range divisors {
		lcmToIdx[v] = idx
	}
	for d := 0; d <= 9; d++ {
		for idx, val := range divisors {
			if d == 0 {
				nextLcm[d][idx] = idx
			} else {
				newL := lcm(val, d)
				nextLcm[d][idx] = lcmToIdx[newL]
			}
		}
	}
	for mod := 0; mod < 2520; mod++ {
		for idx, val := range divisors {
			isValid[mod][idx] = (mod % val == 0)
		}
	}
}

func countBeautiful(x int64) int64 {
	if x <= 0 {
		return 0
	}
	s := fmt.Sprintf("%d", x)
	digits := make([]int, len(s))
	for i, c := range s {
		digits[i] = int(c - '0')
	}
	n := len(digits)

	memoSize := n * 2520 * numDiv
	memo := make([]int64, memoSize)
	for i := range memo {
		memo[i] = -1
	}

	var dfs func(pos, mod, lcmIdx int, tight bool) int64
	dfs = func(pos, mod, lcmIdx int, tight bool) int64 {
		if pos == n {
			if isValid[mod][lcmIdx] {
				return 1
			}
			return 0
		}
		if !tight {
			idx := pos*2520*numDiv + mod*numDiv + lcmIdx
			if memo[idx] != -1 {
				return memo[idx]
			}
		}
		limit := 9
		if tight {
			limit = digits[pos]
		}
		var ans int64 = 0
		for d := 0; d <= limit; d++ {
			newMod := (mod*10 + d) % 2520
			newLcmIdx := nextLcm[d][lcmIdx]
			newTight := tight && d == limit
			ans += dfs(pos+1, newMod, newLcmIdx, newTight)
		}
		if !tight {
			idx := pos*2520*numDiv + mod*numDiv + lcmIdx
			memo[idx] = ans
		}
		return ans
	}

	return dfs(0, 0, lcmToIdx[1], true) - 1
}

func main() {
	var t int
	fmt.Scan(&t)
	for i := 0; i < t; i++ {
		var l, r int64
		fmt.Scan(&l, &r)
		res := countBeautiful(r) - countBeautiful(l-1)
		fmt.Println(res)
	}
}
```