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): 1099


Problem Description
If 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.
 

 

Input
The 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).
 

 

Output
For test case X, output "Case #X: " first, then output the number of good numbers in a single line.
 

 

Sample Input
2
1 10
1 20
 
 

 

Sample Output
Case #1: 0 Case #2: 1
Hint
The 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\n",cnt++,solve(b)-solve(a-1));
48     }
49     return 0;
50 }

 

posted on 2015-08-10 13:05  鱼泪儿  阅读(156)  评论(0编辑  收藏  举报

导航