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 }