codeforces 55D 求数字能被自己每个数位上的数整数的统计
如果这个数要被自己的每个数位上的数整除,那么这个数一定能被每个数位上的最小公倍数整除。
那么剩下的就是用记忆话搜索和枚举来解题了。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 typedef long long LL; 7 int const M = 55; 8 int const N = 20; 9 int const MOD= 2520; 10 LL l,r; 11 int bit[N],ln,hash[MOD+1],co; 12 LL dp[N][MOD][M]; 13 void init() 14 { 15 co=0; 16 for(int i=1;i<=MOD;i++) 17 { 18 if(MOD%i==0) 19 { 20 hash[i]=++co; 21 } 22 } 23 } 24 int gcd(int a,int b) 25 { 26 return b==0?a:gcd(b,a%b); 27 } 28 int lcm(LL a,int b) 29 { 30 return a/gcd(a,b)*b; 31 } 32 LL getsum1(int t,int pre,int limit,int llcm) 33 { 34 if(!t)return (!pre)||(pre%llcm==0); 35 if(!limit&&dp[t][pre][hash[llcm]]!=-1)return dp[t][pre][hash[llcm]]; 36 int up=(limit?bit[t]:9); 37 LL ans=0LL; 38 for(int i=0;i<=up;i++) 39 { 40 int nllcm=llcm; 41 if(i)nllcm=lcm(i,llcm); 42 int com=(pre*10+i)%MOD; 43 ans+=getsum1(t-1,com,limit&&(i==up),nllcm); 44 } 45 if(!limit)dp[t][pre][hash[llcm]]=ans; 46 return ans; 47 } 48 LL getsum2(LL n) 49 { 50 for(ln=0;n;n/=10)bit[++ln]=n%10; 51 return getsum1(ln,0,1,1); 52 } 53 int main() 54 { 55 int T; 56 init(); 57 memset(dp,-1,sizeof(dp)); 58 scanf("%d",&T); 59 while(T--) 60 { 61 scanf("%I64d %I64d",&l,&r); 62 printf("%I64d\n",getsum2(r)-getsum2(l-1)); 63 } 64 return 0; 65 }