reference:http://blog.csdn.net/lvshubao1314/article/details/43907225
思路:略。
# include <stdio.h> # include <string.h> # define LL long long # define MOD 2520 LL a[21], index[2521], dp[21][MOD][50]; void init() { int num = 0; for(int i=1; i<=MOD; ++i) if(!(MOD%i)) index[i] = num++;//最小公倍数离散化,优化内存。 } int gcd(int a, int b) { if(b==0) return a; return gcd(b, a%b); } int lcm(int a, int b) { return a/gcd(a, b)*b; } LL dfs(int pos, int sum, int prelcm, bool limit) { if(pos == -1) return sum%prelcm==0; if(!limit && dp[pos][sum][index[prelcm]] != -1) return dp[pos][sum][index[prelcm]]; int up = limit?a[pos]:9; LL ans = 0; for(int i=0; i<=up; ++i) { int newsum = (sum*10+i)%MOD;//2520为1~9的最小公倍数,数值对2520取余,如果该数(比2520大)能被其各位数整除,则它一定能被2520整除。 int newlcm = prelcm; if(i) newlcm = lcm(newlcm, i); ans += dfs(pos-1, newsum, newlcm, limit&&(i==a[pos])); } if(!limit) dp[pos][sum][index[prelcm]] = ans; return ans; } LL solve(LL num) { int len = 0; while(num) { a[len++] = num%10; num /= 10; } return dfs(len-1, 0, 1, true); } int main() { LL n, m; int t; init(); memset(dp, -1, sizeof(dp)); scanf("%d",&t); while(t--) { scanf("%I64d%I64d",&n,&m); printf("%I64d\n",solve(m)-solve(n-1)); } return 0; }