hdu 4389 统计能被自己数位之和整除的数

枚举数位之和,然后取磨直到最后,记忆化减少时间复杂度。

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 typedef long long LL;
 6 int const N = 11;
 7 int const M = 82;
 8 int dp[N][M][M][M];
 9 int bit[N],l,uup;
10 int getsum1(int t,int pre,int sum,int limit,int rest)
11 {
12    if(rest<0)return 0;
13    if(rest>9*t)return 0;
14    if(!t)return (pre%sum==0&&rest==0);
15    if(!limit&&dp[t][pre][sum][rest]!=-1)return dp[t][pre][sum][rest];
16    int up=(limit?bit[t]:9);
17    LL ans=0LL;
18    for(int i=0;i<=up;i++)
19    {
20       ans+=getsum1(t-1,(pre*10+i)%sum,sum,limit&&i==up,rest-i);
21    }
22    if(!limit&&dp[t][pre][sum][rest]==-1)dp[t][pre][sum][rest]=ans;
23    return ans;
24 }
25 int Max(int a,int b)
26 {
27     return a>b?a:b;
28 }
29 int getsum2(LL n)
30 {
31    int sum=0;
32    for(l=0;n;bit[++l]=n%10,sum+=bit[l],n/=10);
33    int ans=0;
34    uup=Max(bit[l]-1+9*(l-1),sum);
35    for(int i=1;i<=uup;i++)
36        ans+=getsum1(l,0,i,1,i);
37    return ans;
38 }
39 int main()
40 {
41     int T;
42     scanf("%d",&T);
43     int t=0;
44     int a,b;
45     memset(dp,-1,sizeof(dp));
46     while(T--)
47     {
48           scanf("%d %d",&a,&b);
49           printf("Case %d: %d\n",++t,getsum2(b)-getsum2(a-1));
50     }
51     return 0;
52 }

 

posted @ 2013-05-08 13:18  诺小J  阅读(154)  评论(0编辑  收藏  举报