题意:
在[A,B]区间内找出满足条件的数有多少个。
条件:这个数本身 能够整除K, 且各位数字之和能够整除K。
思路:
数据范围过大2^31
2^31 = 2147483648 ~ 2*10^10
各位数字之和不会超过 2 + 9 * 9 = 83 , 所以 当K >= 83 时 答案为0
设F[n] 为 [0,n]区间内符合条件的数, 那么 答案就为F[B] - F[A-1].
暴力枚举O(N^2) 针对这么大的数据显然超时。
设f[i][s_mod][x_mod] 为 前i位数字确定时, 当前数(将后面未知数均视为0) 除以K 余x_mod, 各位数字之和除以K 余s_mod时的方案数
则f[i][s_mod][x_mod] = f[i - 1][(s_mod + p) % K][(x_mod * 10 + p) % K] (p = 0, 1, 2, 3, ..., 9)
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 #define LL long long 7 #define MAXN 11 8 int num[MAXN]; 9 int e[MAXN]; 10 LL f[MAXN][100][100]; 11 int A, B, K, len; 12 void init() 13 { 14 e[0] = 1; 15 for(int i = 1; i < MAXN; i ++) 16 e[i] = e[i-1] * 10; 17 } 18 LL func(int x) 19 { 20 // 21 memset(num, 0, sizeof(num)); 22 memset(f, 0, sizeof(f)); 23 int s1 = 0; 24 int s2 = 0; 25 for(int i = 10; i >=0; i --) 26 { 27 num[i] = x % 10; 28 x /= 10; 29 } 30 for(int i = 0; i < 10; i ++) 31 { 32 s1 = (s1 + num[i]) % K; 33 s2 = (s2 * 10 + num[i]) % K; 34 for(int s_mod = 0; s_mod < K; s_mod ++) 35 for(int x_mod = 0; x_mod < K; x_mod ++) 36 for(int p = 0; p < 10; p ++) 37 f[i + 1][(s_mod + p) % K][(x_mod * 10 + p) % K] += f[i][s_mod][x_mod]; 38 for(int j = 0; j < num[i + 1]; j ++) 39 f[i + 1][(s1 + j) % K][(s2 * 10 + j) % K] ++; 40 } 41 if((s1 + num[10]) % K == 0 && (s2 * 10 + num[10]) % K == 0) ++ f[10][0][0]; 42 return f[10][0][0]; 43 } 44 45 int main() 46 { 47 init(); 48 int T; 49 scanf("%d",&T); 50 while(T--) 51 { 52 scanf("%d %d %d",&A, &B, &K); 53 if(K >= 83) 54 printf("0\n"); 55 else 56 printf("%lld\n", func(B) - func(A - 1)); 57 } 58 return 0; 59 }
时间: 2024-10-12 21:35:51