HDU3555 Bomb 数位DP

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555

我的DP方程:f[i][j]表示数的第i位以j开头的数含有49的个数,则状态转移方程为:

  1.j!=4时: f[i][j]=sum{ f[i-1][k] | 0<=k<=9 }

      2.j==4时:f[i][j]=sum{ f[i-1][k] | 0<=k<=9 } - f[i-1][9] + pow(10,i-2)  (因为j=4时,只要i-1位为9,后面的都满足)

这样的转移方程思路比较清晰,在网上看到别人的转移方程是这样的:   

     1.f[i][0]=10*f[i-1][0]-f[i-1][1];           表示不含49的个数
     2.f[i][1]=f[i-1][0];                             表示以9开头不含49的个数
     3.f[i][2]=10*f[i-1][2]+f[i-1][1];          表示含49的个数

的确比我的优化些,把其它不需要的状态放在一起了。

DP1:

 1 //STATUS:C++_AC_15MS_288KB
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<math.h>
 6 #include<iostream>
 7 #include<string>
 8 #include<algorithm>
 9 #include<vector>
10 #include<queue>
11 #include<stack>
12 #include<map>
13 using namespace std;
14 #define LL __int64
15 #define pii pair<int,int>
16 #define Max(a,b) ((a)>(b)?(a):(b))
17 #define Min(a,b) ((a)<(b)?(a):(b))
18 #define mem(a,b) memset(a,b,sizeof(a))
19 #define lson l,mid,rt<<1
20 #define rson mid+1,r,rt<<1|1
21 const int N=65,INF=0x3f3f3f3f,MOD=100000000;
22 //const double DNF=100000000000;
23 
24 LL f[N][11],d[N];
25 int T;
26 LL n;
27 
28 int main()
29 {
30  //   freopen("in.txt","r",stdin);
31     int i,j,len,num[N],k,la;
32     LL t,ans;
33     d[0]=1;
34     for(i=1;i<20;i++)d[i]=d[i-1]*10;
35     f[1][4]=1;
36     for(i=2;i<20;i++){
37         for(j=0;j<10;j++){
38             for(k=0;k<10;k++)f[i][j]+=f[i-1][k];
39             if(j==4){
40                 f[i][j]-=f[i-1][9];
41                 f[i][j]+=d[i-1];
42             }
43         }
44     }
45     scanf("%d",&T);
46     while(T--)
47     {
48         scanf("%I64d",&n);
49         len=0;ans=0;
50         do num[len++]=n%10;
51         while(n/=10);
52         for(i=len-1,la=-1;i>=0;la=num[i--]){
53             for(j=num[i]-1;j>=0;j--)
54                 ans+=f[i][j];
55             if(num[i]==9 && la==4){
56                 for(t=1,i--;i>=0;i--)
57                     t+=num[i]*d[i];
58                 ans+=t;
59             }
60         }
61 
62         printf("%I64d\n",ans);
63     }
64     return 0;
65 }

DP2:

 1 //STATUS:C++_AC_15MS_264KB
 2 #include<stdio.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<math.h>
 6 #include<iostream>
 7 #include<string>
 8 #include<algorithm>
 9 #include<vector>
10 #include<queue>
11 #include<stack>
12 #include<map>
13 using namespace std;
14 #define LL __int64
15 #define pii pair<int,int>
16 #define Max(a,b) ((a)>(b)?(a):(b))
17 #define Min(a,b) ((a)<(b)?(a):(b))
18 #define mem(a,b) memset(a,b,sizeof(a))
19 #define lson l,mid,rt<<1
20 #define rson mid+1,r,rt<<1|1
21 const int N=65,INF=0x3f3f3f3f,MOD=100000000;
22 //const double DNF=100000000000;
23 
24 LL f[N][4],d[N];
25 int T;
26 LL n;
27 
28 int main()
29 {
30  //   freopen("in.txt","r",stdin);
31     int i,j,len,num[N],k,la;
32     LL t,ans;
33     d[0]=1;
34     for(i=1;i<20;i++)d[i]=d[i-1]*10;
35     f[0][0]=10;f[0][1]=1;f[0][2]=0;
36     for(i=1;i<20;i++){
37         f[i][0]=10*f[i-1][0]-f[i-1][1];
38         f[i][1]=f[i-1][0];
39         f[i][2]=10*f[i-1][2]+f[i-1][1];
40     }
41     scanf("%d",&T);
42     while(T--)
43     {
44         scanf("%I64d",&n);
45         len=0;ans=0;
46         do num[len++]=n%10;
47         while(n/=10);
48         for(i=len-1,la=-1;i>=0;la=num[i--]){
49             if(i>0){
50                 ans+=num[i]*f[i-1][2];
51                 if(num[i]>4)ans+=f[i-1][1];
52             }
53             if(num[i]==9 && la==4){
54                 for(t=1,i--;i>=0;i--)
55                     t+=num[i]*d[i];
56                 ans+=t;
57             }
58         }
59 
60         printf("%I64d\n",ans);
61     }
62     return 0;
63 }
原文地址:https://www.cnblogs.com/zhsl/p/2973389.html