HDU 4389 X mod f(x)

题解:f(x)表示x的各个数位的数字之和,求满足x在[a, b]之间且x = 0(mod f(x))的所有x的个数。

解法:数位DP,这道题思维难度一般,但是充分体现了数位DP锻炼代码的特性。

   设d[i][j][k][l]表示长度为i,各位数字之和为j,除以k余l的数的个数。具体状态转移方程见代码。

tag:数位DP

 1 /*
 2  * Author:  Plumrain
 3  * Created Time:  2013-12-16 12:19
 4  * File Name: DP-HDU-4389.cpp
 5  */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 
10 using namespace std;
11 
12 #define CLR(x) memset(x, 0, sizeof(x))
13 #define out(x) cout<<#x<<":"<<(x)<<endl
14 #define tst(a) cout<<#a<<endl
15 typedef long long int64;
16 int dit[20];
17 int64 ten[15];
18 int d[11][85][85][85];
19 
20 void init()
21 {
22     ten[0] = 1;
23     for (int i = 1; i < 15; ++ i)
24         ten[i] = ten[i-1] * 10;
25     
26     CLR (d);
27     for (int i = 0; i < 10; ++ i)
28         for (int j = 1; j < 85; ++ j)
29             ++ d[1][i][j][i%j];
30 
31     for (int i = 2; i < 10; ++ i)
32         for (int j = 0; j < 85; ++ j)
33             for (int k = 1; k < 85; ++ k)
34                 for (int l = 0; l < k; ++ l)
35                     for (int t = 0; t < 10; ++ t) if (j+t < 85)
36                         d[i][j+t][k][(l+t*ten[i-1])%k] += d[i-1][j][k][l];
37 }
38 
39 int gao(int x)
40 {
41     if (x < 10) return x-1;
42     int64 ret = 0, len = 0;
43     while (x){
44         dit[len++] = x % 10;
45         x /= 10;
46     }
47     dit[len] = 0;
48 
49     int64 flag = 0, dt_sum = 0;
50     for (int i = len-1; i > 0; -- i){
51         for (int t = 0; t < dit[i]; ++ t)
52             for (int j = 0; j < 82; ++ j)
53                 for (int l = 0; l < 82; ++ l){
54                     int k = j + t + dt_sum;
55                     if (!k || (flag + t*ten[i] + l) % k != 0) continue;
56                     ret += d[i][j][k][l];
57                 }
58 
59         flag += dit[i] * ten[i]; 
60         dt_sum += dit[i];
61     }
62 
63     for (int i = 0; i < dit[0]; ++ i)
64         if ((flag+i) % (dt_sum+i) == 0) ++ ret;
65     return (int)ret;
66 }
67 
68 int main()
69 {
70     //freopen("a.in","r",stdin);
71     //freopen("my.out","w",stdout);
72     init();
73     int T, test = 0;
74     scanf ("%d", &T);
75     while (T--){
76         int a, b;
77         scanf ("%d%d", &a, &b);
78         printf ("Case %d: %d
", ++test, gao(b+1) - gao(a));
79     }
80     return 0;
81 }
View Code
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
原文地址:https://www.cnblogs.com/plumrain/p/HDU_4389.html