HDU 4722 Good Numbers(位数DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)

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

Output

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

 

题目大意:求a~b中,位上所有数字加起来能整除10的数有多少个。

思路:位数DP。dp[i][j][k]表示第i位小于j,除以10余k的数的个数,j=10只是为了i+1的j=1准备的……第一次写这个写得有点挫啊……

PS:有数学方法但是我不会,我只知道接近于对于0~n接近于n/10……

 

代码(109MS):

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 const int MAXN = 22;
 9 
10 LL dp[MAXN][MAXN][MAXN];
11 //i位,字头小于j,和为k的数一共有多少个
12 LL a, b;
13 int T;
14 
15 void init() {
16     dp[0][10][0] = 1;
17     for(int i = 1; i <= 19; ++i) {
18         for(int k = 0; k <= 9; ++k) dp[i][1][k] = dp[i - 1][10][k];
19         for(int j = 2; j <= 10; ++j) {
20             for(int k = 0; k <= 9; ++k)
21                 dp[i][j][k] = dp[i][1][(k + 10 - (j - 1)) % 10] + dp[i][j - 1][k];
22         }
23     }
24 }
25 
26 int t[MAXN];
27 
28 LL calculate(LL n) {
29     int cnt = 0;
30     while(n) t[++cnt] = n % 10, n /= 10;
31     int sum = 0;
32     LL ret = 0;
33     for(int i = cnt; i > 0; --i) {
34         ret += dp[i][t[i]][(10 - sum) % 10];
35         sum = (sum + t[i]) % 10;
36     }
37     return ret;
38 }
39 
40 int main() {
41     ios::sync_with_stdio(false);
42     cin>>T;
43     init();
44     for(int t = 1; t <= T; ++t) {
45         cin>>a>>b;
46         cout<<"Case #"<<t<<": "<<calculate(b + 1) - calculate(a)<<endl;
47     }
48 }
View Code

 

posted @ 2013-09-11 22:17  Oyking  阅读(404)  评论(0编辑  收藏  举报