【數位DP】 【CodeForces 55D】
阿新 • • 發佈:2019-02-11
題意:求區間[a, b]中有多少個數能整除自身的每個非0數位。
分析:一個數位只有1~9種可能,而1~9的lcm=2520。滿足要求的數所有數位的lcm一定是2520的因子,
所以可先求出2520的所有因子,一開始都對2520取mod,這樣對結果沒有任何影響,最後再對所有數
位的lcm取mod,如果為0則滿足。
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<map> using namespace std; typedef long long LL; const int maxn=2520; int digit[20], a[50], t=0; LL dp[20][maxn][50]; map<int,int>m; int GCD(int a, int b) { return b==0?a:GCD(b, a%b); } int LCM(int a, int b) { return a/GCD(a,b)*b; } LL dfs(int pos, int mod, int lcm, bool limit) { if(!pos) return (mod%a[lcm]==0); if(!limit&&dp[pos][mod][lcm]!=-1) return dp[pos][mod][lcm]; int len=(limit?digit[pos]:9); LL ret=0LL; for(int i=0; i<=len; ++i) ret+=dfs(pos-1, (mod*10+i)%maxn, i==0?lcm:m[LCM(a[lcm],i)], limit&&i==len); if(!limit) dp[pos][mod][lcm]=ret; return ret; } LL work(LL x) { int len=0; while(x) digit[++len]=x%10, x/=10; return dfs(len, 0, 0, true); } int main() { memset(dp, -1, sizeof(dp)); for(int i=1; i<=maxn; ++i) if(maxn%i==0) a[t]=i, m[i]=t++; int T; cin>>T; while(T--) { LL a, b; cin>>a>>b; cout<<work(b)-work(a-1)<<endl; } return 0; }