Description:

Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.

Input:

The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).
Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).

Output

Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).

Sample Input:

1
1 9

Sample Output:

9

Sample Input:

1
12 15

Sample Output:

2

题目链接

数位dp从高数位向低数位记忆化搜索。

AC代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 50;
const int mod = 2520;

long long Index[mod + 5];
long long Digit[maxn];
long long Dp[maxn][mod + 5][maxn];

void Init() {
    int Num = 0;
    for (int i = 1; i <= mod; ++i) {
        if (mod % i == 0) {
            Index[i] = Num++;
        }
    }
    memset(Dp, -1, sizeof(Dp));
}

// 最小公倍数
inline long long __Lcm(long long A, long long B) {
    return (A * B) / __gcd(A, B);
}

// 深搜,Len:当前数位,Sum:高数位对2520的模,Lcm:高数位的最小公倍数,Flag:前位是否达上限
long long Dfs(int Len, int Mod, int Lcm, bool Flag) {
    // 搜到最后一位
    if (Len == 0) {
        return Mod % Lcm == 0;
    }
    if (!Flag && ~Dp[Len][Mod][Index[Lcm]]) {
        return Dp[Len][Mod][Index[Lcm]];
    }
    long long Ans = 0;
    // 当前位可达的最大数
    int Up = Flag ? Digit[Len] : 9;
    // 枚举当前位所有可能数并继续向低数位
    for (long long i = 0; i <= Up; ++i) {
        long long NowLcm = Lcm;
        if (i) {
            NowLcm = __Lcm(NowLcm, i);
        }
        Ans += Dfs(Len - 1, (Mod * 10 + i) % mod, NowLcm, Flag && i == Up);
    }
    return Flag ? Ans : Dp[Len][Mod][Index[Lcm]] = Ans;
}

long long Cal(long long X) {
    // 数字按位分解
    int Len = 0;
    while (X) {
        Digit[++Len] = X % 10;
        X /= 10;
    }
    return Dfs(Len, 0, 1, 1);
}

int main(int argc, char *argv[]) {
    Init();
    long long T;
    scanf("%lld", &T);
    for (long long Case = 1, Left, Right; Case <= T; ++Case) {
        scanf("%lld%lld", &Left, &Right);
        printf("%lld\n", Cal(Right) - Cal(Left - 1));
    }
    return 0;
}