Output
2
题意:求区间内能整除自己每位数(0除外)的个数。
code:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#define ll long long
#define Mod 2520 ////1-9的最小公倍数
using namespace std;
ll l,r;
ll dp[30][Mod][50];///dp[i][j][k] i:长度 j:各个位数最小公倍数对Mod取摸 k:最小公倍数对应的值得离散下标
int num[30];
int b[Mod+1]; ///记录最小公倍数
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
ll Lcm(ll a,ll b) {
return a/gcd(a,b)*b;
}
ll dfs(int i,ll lcm,ll sum,bool e) {
if(i<=0)return sum%lcm==0;
if(!e&&dp[i][sum][b[lcm]]!=-1)return dp[i][sum][b[lcm]];
ll res=0;
int u=e?num[i]:9;
for(ll d=0; d<=u; d++) {
if(d==0) ///d==0时,lcm不变
res+=dfs(i-1,lcm,sum*10%Mod,e&&d==u);
else
res+=dfs(i-1,lcm*d/gcd(lcm,d),(sum*10+d)%Mod,e&&d==u);
}
return e?res:dp[i][sum][b[lcm]]=res;
}
ll solve(ll n) {
int len=1;
while(n) {
num[len++]=n%10;
n/=10;
}
return dfs(len-1,1,0,1);
}
int main() {
memset(dp,-1,sizeof dp);
int cnt=0;
///离散记录lcm值
for(int i=1; i<=Mod; i++)if(Mod%i==0)b[i]=cnt++;
int t;
scanf("%d",&t);
while(t--) {
scanf("%I64d%I64d",&l,&r);
ll ans=solve(r)-solve(l-1);
printf("%I64d\n",ans);
}
return 0;
}