Codeforces 55D Beautiful numbers

题意:统计某段区间内满足它所有非零数位能整除这个数本身的数的个数。

解法;

  自己搞的时候除了想到开N维数组分别记录之外没什么别的想法><

  2~9所有数的lcm最大是2520,dp[pos][pre_mod][pre_lcm]记录前pos位数对2520取余为pre_mod并且非零位的lcm位pre_lcm的个数。

  因为2到9的lcm最多只有不到50个,我们需要对lcm离散化一下。。。。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 25
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn=2600;
 9 const int mod=2520;
10 ll dp[N][maxn][50];
11 int hash[maxn];
12 int bit[N];
13 void init(){
14     int cnt=0;
15     for(int i=1;i<=mod;i++){
16         if(mod%i==0){
17             hash[i]=++cnt;
18         }
19     }
20 }
21 int gcd(int a,int b){
22     for(int r=a%b;r;a=b,b=r,r=a%b);
23     return b;
24 }
25 int lcm(int a,int b){
26     return a/gcd(a,b)*b;
27 }
28 ll dfs(int pos,int pre_mod,int pre_lcm,bool flag){
29     if(pos==0)return pre_mod%pre_lcm==0;
30     if(flag&&~dp[pos][pre_mod][hash[pre_lcm]])return dp[pos][pre_mod][hash[pre_lcm]];
31     int u=flag?9:bit[pos];
32     ll ans=0;
33     int next_mod,next_lcm;
34     for(int d=0;d<=u;d++){
35         next_mod=(pre_mod*10+d)%mod;
36         next_lcm=pre_lcm;
37         if(d)next_lcm=lcm(pre_lcm,d);
38         ans+=dfs(pos-1,next_mod,next_lcm,flag||d<u);
39     }
40     if(flag)dp[pos][pre_mod][hash[pre_lcm]]=ans;
41     return  ans;
42 }
43 ll solve(ll n){
44     int len=0;
45     while(n>0){
46         bit[++len]=n%10;
47         n/=10;
48     }
49     return dfs(len,0,1,0);
50 }
51 int main(){
52     init();
53     int t;
54     ll l,r;
55     cin>>t;
56     memset(dp,-1,sizeof(dp));
57     while(t--){
58         cin>>l>>r;
59         ll ans=solve(r)-solve(l-1);
60         cout<<ans<<endl;
61     }
62     return 0;
63 }

 

posted @ 2013-03-11 20:29  silver__bullet  阅读(1163)  评论(0编辑  收藏  举报