dp[i][lcm][mod]
i 推到第几位
lcm 为 比i高的位的值的最小公倍数,
mod为此时的数值 %(lcm(1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520)的价值
dp[i][lcm][mod] 的值为这个状态时 0 - (i -1)位选择的方案数使其最后数值%所有位的lcm为0
因为2520能够整除任意由1 - 9 形成的最小公倍数所以%2520 最后判断 mod % lcm 等于0就合法 不是就不合法
要把1 - 9 形成的所有最小公倍数离散化
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#define LL long long
#define mod 2520
using namespace std;
vector<LL>ve;
LL dp[30][55][2600];
LL has[2000];
LL x[50], l;
LL gcd(LL a, LL b)
{
while(b)
{
int t = a %b;
a = b;
b = t;
}
return a;
}
LL dfs(int i, bool e, int lcm, LL pre)
{
if(i == -1)
{
if(pre % lcm == 0) return 1;
else return 0;
}
if(e && dp[i][has[lcm]][pre % mod] != -1) return dp[i][has[lcm]][pre % mod];
LL Max = e ? 9 : x[i], ans = 0;
for(int j = 0; j <= Max; j++)
if(j!=0)ans += dfs(i - 1, !(!e && j == x[i]), lcm * j / gcd(lcm, j), (pre * 10 + j) % mod);
else ans += dfs(i - 1, !(!e && j == x[i]), lcm, (pre * 10 + j) % mod);
if(e) dp[i][has[lcm]][pre] = ans;
return ans;
}
LL cal(LL n)
{
l = 0;
while(n)
{
x[l++] = n % 10ll;
n /= 10ll;
}
return dfs(l - 1, 0, 1, 0);
}
void dfs2(int pre,int i)
{
ve.push_back(pre);
for(int j = i; j<= 9; j++)
dfs2(pre * j / gcd(pre, j), j + 1);
}
int main()
{
dfs2(1,1);
sort(ve.begin(), ve.end());
vector<LL>::iterator it = unique(ve.begin(),ve.end());
ve.erase(it,ve.end());
for(int i = 0; i < ve.size(); i++) has[ve[i]] = i;
memset(dp, -1, sizeof(dp));
LL a, b, t;
scanf("%I64d", &t);
while(t--)
{
scanf("%I64d %I64d", &a, &b);
printf("%I64d\n", cal(b) - cal(a - 1));
}
return 0;
}