CodeForces - 55D Beautiful numbers
Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.
Input
The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri(1 ≤ li ≤ ri ≤ 9 ·1018).
Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).
Output
Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).
Example
1
1 9
9
1
12 15
2
目前为止见过的一道比较难的dp题了,再参考了网上的一大堆代码后终于写出来了中间TLE了无数次。。。。
原理很简单,就是暴力遍历,先考虑题意是:该数能被其每一位上的数字整除 等价于 该数可以整除它每一位数的最小公倍数。。。
然后1-9的最小公倍数是2520,这样它如果是2520的倍数,一定是1-9所有数的倍数。。。
结果核心的地方还好写。。。然后就是疯狂的TTTT。。。
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <algorithm> #include <queue> #include <vector> #include <math.h> #include <string.h> using namespace std; #define INF 0x3f3f3f3f #define N 20 #define PI acos(-1) #define mod 2520 #define LL long long /********************************************************/ LL dp[20][50][2520],d[20], num[mod+5]; LL gcd(LL a, LL b) { if(b==0) return a; else return gcd(b, a%b); } LL dfs(int now, int w, int lcm, int fp)///now表示当前位置;w表示当前位前的所有数对2520取余;lcm为当前位及之前位的最小公倍数;fp记录是否达到上限值 { if(now==-1) return w%lcm==0; if(!fp&&~dp[now][num[lcm]][w]) return dp[now][num[lcm]][w];///这里必须逐位取反,否则会T LL ans=0; int len=fp?d[now]:9; for(int i=0;i<=len;i++) ans+=dfs(now-1, (w*10+i)%mod, i?lcm*i/gcd(lcm,i):lcm, fp&&i==len); if(!fp) dp[now][num[lcm]][w]=ans; return ans; } LL solve(LL X) { int len=0; while(X) { d[len++]=X%10; X/=10; } return dfs(len-1, 0, 1, 1); } int main() { LL n,m; int cnt=0; int T; for(int i=1;i<=mod;i++) { if(mod%i==0) num[i]=cnt++; }///提前存储能被整除的数 memset(dp,-1,sizeof(dp));///初始化放在函数中会T scanf("%d", &T); while(T--) { scanf("%lld%lld",&n,&m), printf("%lld\n", solve(m)-solve(n-1)); } return 0; }