hdu3652 B-number 数位DP

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

题意就是求区间内能被13整除并且包含”13“的数字的个数

感觉是比较中等的数位DP题目

我用的记忆化的方式做的

定义dp[len][mod][mark];

其中len表示当前正在处理的位数或可以理解为还有len位需要处理,mod表示当前的总的余数(即从最高位到len位时所计算得到的余数)

mark起标记作用

mark==0表示从最高位到i位还没有出现”13“;

mak==1表示从最高位到i位没有出现”13“,但第i位为1

mark==2表示从最高位到i位包含”13“

具体实现如下:

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 int n;
 7 int len;
 8 int bit[40];
 9 int dp[40][14][4];
10 
11 void init(int n)
12 {
13       memset(dp,-1,sizeof(dp));
14      len=0;
15     while(n)
16     {
17        bit[++len]=n%10;
18        n/=10;
19     }
20 
21 }
22 int dfs(int len,int mod,int mark,int flag)
23 {
24    int sum=0;
25    if(len==0) return  mod==0 && mark==2;
26    if(flag && dp[len][mod][mark]>=0) return dp[len][mod][mark];
27    int tmp=flag?9:bit[len];
28 
29    for(int i=0;i<=tmp;i++)
30    {
31       int Mod=(mod*10+i)%13;
32 
33       int Mark=mark;
34       if(mark!=2 && i!=1) Mark=0;
35       if(mark!=2 && i==1) Mark=1;
36       if(mark==1 && i==3 )Mark=2;
37       sum+=dfs(len-1,Mod,Mark,flag||i<tmp);
38    }
39    if(flag) dp[len][mod][mark]=sum;
40    return sum;
41 
42 }
43 int main()
44 {
45    while(scanf("%d",&n)!=EOF)
46    {
47       init(n);
48       cout<<dfs(len,0,0,0)<<endl;
49    }
50    return 0;
51 }
原文地址:https://www.cnblogs.com/xiaozhuyang/p/hdu3652.html