题目链接:http://lightoj.com/volume_showproblem.php?problem=1068
题目大意:给你三个数,l, r, k,问[l,r] 这个范围内,有多少个数满足该数能被k整除,且所有数位和能被k整除
解题思路:一个大剪枝,因为给的数字是小于2^31,10位数,且最高位为2,所以最大的数位和就不会超过90了,所以k超过90的,答案都是0
接下来就是数位DP了,用dp[pos][sum][mod]表示当前在i位,前面所有数位的和和k的余数是sum,前面的数和k的余数是mod
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <ctime> 8 #include <queue> 9 #include <list> 10 #include <set> 11 #include <map> 12 using namespace std; 13 #define INF 0x3f3f3f3f 14 typedef long long LL; 15 16 int bit[15], k, dp[15][100][100]; 17 int dfs(int len, int sum, int re, int flag) 18 { 19 if(len < 1) 20 return (sum % k)==0 && re == 0; 21 if(flag && dp[len][sum][re] != -1) 22 return dp[len][sum][re]; 23 int te = flag ? 9 : bit[len]; 24 int res = 0; 25 for(int i = 0; i <= te; i++) 26 { 27 res += dfs(len-1, sum + i, (re*10+i)%k, flag || i < te); 28 } 29 if(flag) 30 dp[len][sum][re] = res; 31 return res; 32 } 33 int solve(int n) 34 { 35 int len = 0; 36 while(n) 37 { 38 bit[++len] = n % 10; 39 n /= 10; 40 } 41 return dfs(len, 0, 0, 0); 42 } 43 int main() 44 { 45 int t, a, b; 46 scanf("%d", &t); 47 for(int ca = 1; ca <= t; ca++) 48 { 49 scanf("%d %d %d", &a, &b, &k); 50 memset(dp, -1, sizeof(dp)); 51 if(k >= 90)//不知道为什么加上这段就ac了,明明是一样的效果 52 { 53 printf("Case %d: 0\n", ca); 54 continue; 55 } 56 int res = solve(b) - solve(a-1); 57 printf("Case %d: %d\n", ca, res); 58 } 59 return 0; 60 }