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

 

你可能感兴趣的:(number)