hdu 4722 Good Numbers( 数位dp入门) Good Numbers
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3467 Accepted Submission(s): 1099Problem DescriptionIf we sum up every digit of a number and the result can be exactly divided by 10, we say this number is a good number.
You are required to count the number of good numbers in the range from A to B, inclusive.InputThe first line has a number T (T <= 10000) , indicating the number of test cases.
Each test case comes with a single line with two numbers A and B (0 <= A <= B <= 1018).OutputFor test case X, output "Case #X: " first, then output the number of good numbers in a single line.Sample Input21 101 20Sample OutputCase #1: 0 Case #2: 1HintThe answer maybe very large, we recommend you to use long long instead of int.Source
题意:给定区间A到B(用 long long),求其间好数有多少,好数是指每位数字加起来的和对10取余结果是0。
当时不明白何为学长讲的边界,另外数位dp还有递推版,但是递推太容易出错,还是记忆化搜索比较容易理解~
1 #include<iostream> 2 #include<vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <math.h> 7 #include<algorithm> 8 #define ll long long 9 #define eps 1e-8 10 using namespace std; 11 ll dp[20][20]; // 统计第几位数余数为几有多少个 12 int num[20]; //存放每位数字 13 ll dfs(int site,int mod,int f) 14 { 15 if(site == 0) 16 return mod == 0 ? 1:0; // 递归结束条件,并判断最后一位时是否余数为0 17 if(!f && dp[site][mod] != -1) //记忆化搜索 18 return dp[site][mod]; 19 int len = f == 1?num[site]:9; //若当前位为边界則当前位只枚举0-当前,否则枚举0-9 20 ll ans = 0; 21 for(int i = 0; i <= len; i++) 22 ans += dfs(site-1,(mod+i)%10,f && i == len);//f判断是否为边界 23 if(!f) 24 dp[site][mod] = ans; //边界不能存,因为之前计算的是不看边界的,便于以后用到,如果存了,就是一个错误的统计 25 return ans; 26 } 27 ll solve(ll digit) 28 { 29 memset(num,0,sizeof(num)); 30 int l = 0; 31 while(digit) 32 { 33 num[++l] = digit%10; 34 digit /= 10; 35 } 36 return dfs(l,0,1); 37 } 38 int main(void) 39 { 40 int t,cnt = 1; 41 ll a,b; 42 memset(dp,-1,sizeof(dp)); 43 scanf("%d",&t); 44 while(t--) 45 { 46 scanf("%lld %lld",&a,&b); 47 printf("Case #%d: %lld ",cnt++,solve(b)-solve(a-1)); 48 } 49 return 0; 50 }