数位DP(基础,模板)
共两题
一:
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3555
所看代码来源:
https://blog.csdn.net/u012860063/article/details/46820639
Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 21701 Accepted Submission(s): 8137
Problem Description
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
Input
The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.
The input terminates by end of file marker.
The input terminates by end of file marker.
Output
For each test case, output an integer indicating the final points of the power.
Sample Input
3
1
50
500
Sample Output
0 1 15
View Code
Hint
From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 long long dp[25][3]; 7 int digite[25]; 8 long long n; 9 //dp[i][j]:长度为i的数的第j种状态 10 //dp[i][0]:长度为i但是不包含49的方案数 11 //dp[i][1]:长度为i且不含49但是以9开头的数字的方案数 12 //dp[i][2]:长度为i且包含49的方案数 13 long long DFS(int pos,int status,int limit) 14 { 15 long long end; 16 if (pos<=0) 17 return status==2;//注意是==; 18 if(!limit && dp[pos][status]!=-1)////对于有限制的询问我们是不能够记忆化的 19 return dp[pos][status]; 20 long long ans=0; 21 if (limit==0) 22 end=9; 23 else 24 end=digite[pos]; 25 for (int i=0;i<=end;i++) 26 { 27 int nstatus=status; 28 if(status==0 && i==4)//高位不含49,并且末尾不是4 ,现在末尾添4返回1状态 29 nstatus = 1; 30 else if(status==1 && i!=4 && i!=9)//高位不含49,且末尾是4,现在末尾添加的不是4返回0状态 31 nstatus = 0; 32 else if(status==1 && i==9)//高位不含49,且末尾是4,现在末尾添加9返回2状态 33 nstatus = 2; 34 ans+=DFS(pos-1,nstatus,i==end&&limit); 35 } 36 if (!limit) 37 { 38 dp[pos][status]=ans; 39 } 40 return ans; 41 } 42 int cal(long long x) 43 { 44 int cnt=0; 45 while (x) 46 { 47 digite[++cnt]=x%10; 48 x=x/10; 49 } 50 digite[cnt+1]=0; 51 return cnt; 52 } 53 int main() 54 { 55 int T; 56 scanf("%d",&T); 57 while (T--) 58 { 59 memset(dp,-1,sizeof(dp)); 60 scanf("%lld",&n); 61 long long len=cal(n); 62 long long ans=DFS(len,0,1); 63 printf("%lld\n",ans); 64 } 65 return 0; 66 }
二:进化版
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3652
所看博客:https://blog.csdn.net/qq_33583069/article/details/51842294
B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8032 Accepted Submission(s): 4738
Problem Description
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13
100
200
1000
Sample Output
1
1
2
2
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 long long dp[25][15][3]; 7 //dp[i][j][k] 8 //i:数位 9 //j:余数 10 //k:3种操作状况,0:末尾不是1,1:末尾是1,2:含有13 11 int digite[25]; 12 long long n; 13 long long DFS(int pos,int mod,int status,int limit) 14 { 15 long long end; 16 if (pos<=0) 17 return status==2&&mod==0;//注意是==; 18 if(!limit && dp[pos][mod][status]!=-1) 19 return dp[pos][mod][status]; 20 long long ans=0; 21 if (limit==0) 22 end=9; 23 else 24 end=digite[pos]; 25 for (int i=0;i<=end;i++) 26 { 27 int modx=(mod*10+i)%13;//巧用余数 28 int nstatus=status; 29 if(status==0 && i==1) 30 nstatus = 1; 31 else if(status==1 && i!=1 && i!=3) 32 nstatus = 0; 33 else if(status==1 && i==3) 34 nstatus = 2; 35 ans+=DFS(pos-1,modx,nstatus,i==end&&limit); 36 } 37 if (!limit) 38 { 39 dp[pos][mod][status]=ans; 40 } 41 return ans; 42 } 43 int cal(long long x) 44 { 45 int cnt=0; 46 while (x) 47 { 48 digite[++cnt]=x%10; 49 x=x/10; 50 } 51 digite[cnt+1]=0; 52 return cnt; 53 } 54 int main() 55 { 56 int T; 57 while (scanf("%lld",&n)!=EOF) 58 { 59 memset(dp,-1,sizeof(dp)); 60 long long len=cal(n); 61 long long ans=DFS(len,0,0,1); 62 printf("%lld\n",ans); 63 } 64 return 0; 65 }