思路:
要找一个数能被他的所有反的数字整除,只需求出这个数能被其数字的LCM整除。而LCM最大为5*7*8*9=2520;
如果直接开dp[20][2520][2520]会超内存,而2^3,3^2,5,7的组合只有4*3*2*2=48种,所以开dp[20][2520][50]即可。
链接:http://codeforces.com/problemset/problem/55/D
代码如下:

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll __int64 5 using namespace std; 6 int bit[20],hash[2529]; 7 ll dp[20][2521][50]; 8 int gcd(int a,int b) 9 { 10 if(a<b) swap(a,b); 11 while(b){ 12 int t=a; 13 a=b; 14 b=t%b; 15 } 16 return a; 17 } 18 ll dfs(int pos,int num,int lcm,bool f) 19 { 20 if(pos==-1) return num%lcm==0; 21 if(!f&&dp[pos][num][hash[lcm]]!=-1) return dp[pos][num][hash[lcm]]; 22 ll ans=0; 23 int e=f?bit[pos]:9; 24 for(int i=0;i<=e;i++){ 25 int g=lcm; 26 if(i>=2) g=g/gcd(g,i)*i; 27 ans+=dfs(pos-1,(num*10+i)%2520,g,f&&(i==bit[pos])); 28 } 29 if(!f) dp[pos][num][hash[lcm]]=ans; 30 return ans; 31 } 32 ll cal(ll n) 33 { 34 int m=0; 35 while(n){ 36 bit[m++]=n%10; 37 n/=10; 38 } 39 return dfs(m-1,0,1,1); 40 } 41 int main() 42 { 43 ll n,m; 44 int t,i,j; 45 memset(dp,-1,sizeof(dp)); 46 for(j=0,i=1;i<=2520;i++){ 47 if(2520%i==0) 48 hash[i]=j++; 49 } 50 scanf("%d",&t); 51 while(t--){ 52 scanf("%I64d%I64d",&n,&m); 53 printf("%I64d ",cal(m)-cal(n-1)); 54 } 55 }