1. 程式人生 > 實用技巧 >Codeforces Beta Round #51 D. Beautiful numbers

Codeforces Beta Round #51 D. Beautiful numbers

http://codeforces.com/contest/55/problem/D

題意:

詢問[l,r]內有多少個數字,滿足能被自己的每一位非0數整除

數位DP

表示出當前對2520取模的餘數,以及目前各個數位數字的最小公倍數

因為0—9的最小公倍數是2520,而且最小公倍數只有48種情況

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
     
    using namespace std;
     
    typedef 
long long LL; const int mod=2520; int num[21]; int lcm[11][2525],li[2525],il[51],sl; LL dp[21][2525][51]; LL dfs(int dep,bool lim,int r,int lc) { if(!lim && dp[dep][r][li[lc]]!=-1) return dp[dep][r][li[lc]]; if(!dep) return !(r%lc);
bool nlim; int nr,nlcm; LL sum=0; int up=lim ? num[dep] : 9; for(int i=0;i<=up;++i) { nlim=(lim && i==num[dep]); nr=(r*10+i)%mod; nlcm=lcm[i][lc]; sum+=dfs(dep-1,nlim,nr,nlcm); } if(!lim) dp[dep][r][li[lc]]=sum;
return sum; } LL solve(LL n) { int m=0; while(n) num[++m]=n%10,n/=10; return dfs(m,1,0,1); } void pre() { for(int i=0;i<=9;++i) for(int j=1;j<=mod;++j) { if(!i) lcm[i][j]=j; else lcm[i][j]=i*j/__gcd(i,j); } sl=0; int t; for(int i=0,t2=1;i<=3;++i,t2*=2) for(int j=0,t3=1;j<=2;++j,t3*=3) for(int k=0,t5=1;k<=1;++k,t5*=5) for(int l=0,t7=1;l<=1;++l,t7*=7) { t=t2*t3*t5*t7; li[t]=++sl; il[sl]=t; } } int main() { memset(dp,-1,sizeof(dp)); int T; LL l,r; pre(); scanf("%d",&T); while(T--) { cin>>l>>r; cout<<solve(r)-solve(l-1)<<'\n'; } }