问区间[L,R] 之间有多少个数满足,这个数能够整除这个数的每一个数位,比如36可以整除3和6,所以是符合要求的数字。
直接看来,一个数每一位还没有确定的时候,就无法知道这个数能不能整除自己的每一位。
假如这个数是可以整除自己的每一位,也就是说这个数是自己每一位的公倍数,比如一个满足的数X组成是abc的形式,那么X是a的倍数,b的倍数,c的倍数,也就是X%lcm(a,b,c)==0。然后1-9的lcm是2520,也就是2520能整除1-9的任意组合,利用这些性质,就可以进行空间的压缩离散
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
#define gcd __gcd
#define LCM(x,y) x/gcd(x,y)*y
#define dbg(x) printf("deg: # ::: %d\n",x);
#define cl(a,b) memset(a,b,sizeof(a))
const int maxn = 1005;
LL dp[20][2521][50];
int Lcm[2521];//离散 保证dp可以开下空间
int bit[20];
void init(){
for(int i=1,j=0;i<=2520;i++)if(2520%i==0)
Lcm[i]=j++;
}
LL dfs(int i,int s,int lm,bool e){
if(i == 0) return s % lm== 0;
if(!e && ~dp[i][s][Lcm[lm]]) return dp[i][s][Lcm[lm]];
LL ans = 0;
int u = e?bit[i]:9;
for(int d=0;d<=u;d++){
ans+=dfs(i-1,(s*10+d)%2520,d?LCM(lm,d):lm,e&&d==u);
}
return e?ans:dp[i][s][Lcm[lm]]=ans;
}
LL f(LL num){
int len=0;
while(num){
bit[++len]=num%10;
num/=10;
}
return dfs(len,0,1,1);
}
int main(){
int T;init();
scanf("%d",&T);cl(dp,-1);
while(T--){
LL L,R;scanf("%lld%lld",&L,&R);
printf("%lld\n",f(R)-f(L-1));
}
return 0;
}