HDU - 4722 Good Numbers 找规律 or 数位dp模板

Posted euzmin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 4722 Good Numbers 找规律 or 数位dp模板相关的知识,希望对你有一定的参考价值。

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.

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 <= 10 18).OutputFor 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.

        
 这题有两种做法,找规律或者数位dp
法一找规律:从0开始打表会发现每10个数都有一个good number 0 - 9, 10- 19 …… 这样假如要求0 到123,只需要求 0 - 119的 有12个good numbers,再暴力求120 - 123的即可。
法二数位dp:这道题在数位dp中算是模板入门了吧。

法一代码:
技术分享图片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 #include <set>
10 #include <cstring>
11 using namespace std;
12 typedef long long ll;
13 #define inf 0x3f3f3f3f
14 char st[12];
15 ll x;
16 int main()
17 {
18     int t;
19     ll a, b;
20     scanf("%d", &t);
21     ll cnta = 0, cntb = 0;
22     for(int cas = 1; cas <= t; ++cas) {
23         cnta = 0;
24         cntb = 0;
25         scanf("%lld %lld", &a, &b);
26         a--;
27         if(a < 0) cnta--;
28         a = max(a, ll(0));
29         ll ma = a % 10;
30         cnta += a / 10;
31         for(ll i = 0; i <= ma; ++i) {
32             ll sum = 0;
33             ll v = a / 10 * 10+ i;
34             while(v) {
35                 sum += v % 10;
36                 v /= 10;
37             }
38             if(sum % 10 == 0) cnta++;
39         }
40         ll mb = b % 10;
41         cntb += b / 10;
42         for(ll i = 0; i <= mb; ++i) {
43             ll sum = 0;
44             ll v = b / 10 * 10+ i;
45             while(v) {
46                 sum += v % 10;
47                 v /= 10;
48             }
49             if(sum % 10 == 0) cntb++;
50         }
51         
52         printf("Case #%d: %lld\n", cas, cntb - cnta);
53     }
54     return 0;
55 }
View Code

法二代码:

技术分享图片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 #include <set>
10 #include <cstring>
11 using namespace std;
12 typedef long long ll;
13 #define inf 0x3f3f3f3f
14 ll dp[22][188];
15 ll ed[22];
16 ll dfs(int pos, ll sum, bool lmt) {
17     if(pos == 0) {
18         if(sum % 10 == 0) return 1;
19         return 0;
20     }
21     
22     if(!lmt && dp[pos][sum] != -1) return dp[pos][sum];
23     ll ans = 0;
24     ll up =  lmt? ed[pos] : 9;
25     for(ll i = 0; i <= up; ++i) {
26         ans += dfs(pos - 1, sum + i, lmt && i == ed[pos]);
27     }
28     if(!lmt) dp[pos][sum] = ans;//统计状态
29     return ans;
30 }
31 ll solv(ll x) {
32     if(x < 0) return 0;
33     int len = 0;
34     while(x) {
35         ed[++len] = x % 10;
36         x /= 10;
37     }
38     
39     return dfs(len, 0, 1);
40 }
41 
42 int main()
43 {
44     int t;
45     ll a, b;
46     scanf("%d", &t);
47     memset(dp,-1,sizeof(dp));
48     for(int cas = 1; cas <= t; ++cas) {
49         
50         scanf("%lld %lld", &a, &b);
51         printf("Case #%d: %lld\n", cas, solv(b) - solv(a - 1));
52     }
53     return 0;
54 }
View Code

 












以上是关于HDU - 4722 Good Numbers 找规律 or 数位dp模板的主要内容,如果未能解决你的问题,请参考以下文章

HDU5447 Good Numbers

HDU 4722 数位dp

HDU 1847 Good Luck in CET-4 Everybody!(博弈找规律)

Good Numbers

hdu1847 Good Luck in CET-4 Everybody!(巴什博弈)

CodeForces - 1521A Nastia and Nearly Good Numbers