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\n", ++test, gao(b+1) - gao(a)); 79 } 80 return 0; 81 }
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。