link:https://vjudge.net/problem/UVA-11361
An integer is divisible by 3 if the sum of its digits is also divisible by 3. For example, 3702 is divisible
by 3 and 12(3+7+0+2) is also divisible by 3. This property also holds for the integer 9.
In this problem, we will investigate this property for other integers.
Input
The first line of input is an integer T (T < 100) that indicates the number of test cases. Each case is
a line containing 3 positive integers A, B and K. 1 ≤ A ≤ B < 2
31 and 0 < K < 10000.
Output
For each case, output the number of integers in the range [A, B] which is divisible by K and the sum
of its digits is also divisible by K.
Sample Input
3
1 20 1
1 20 2
1 1000 4
Sample Output
20
5
64
题目很短,题意也很简单,要求给定数字范围内的满足整除k且每一位数字加起来也整除k的数字的数量。用dp[i][j][l]表示位数为i,数位和mod k等于j,数字mod k等于l的数字的数量,因为每一次的k都不一样,所以似乎用dfs求dp会比递推好点。题目的k范围为10000,但是数字的上限为2^31,所以数位和最多也不会超过83,dp数组的后两维只需要开这么大就行。在数位统计的时候从高位到低位计数的同时要记录高位固定为最大时的数位和m1和数字和m2,然后枚举当前位x寻找对应位数dp[i][j][l]满足(j+m1+x)%k==0且(l+m2+x*10^i)%k==0的dp值,所以
ans += dfs(i, (K - (m1 + j)%K) % K, (K - (m2 + poww[i] *j)%K)%K);
然后记忆化搜索。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxe = 30005;
const int maxn = 10000;
const int maxk = 505;
const int mod = 1000000000;
int n,m,K;
int poww[12];
int dp[12][105][105];//dp[i][j][k]位数位i,位数字和mod k为j,数字modk为k的数字的数量
int dfs(int a, int m1, int m2){
if (a == 0)return (m1 == 0 && m2 == 0) ? 1 : 0;
if (dp[a][m1][m2] >= 0)return dp[a][m1][m2];
dp[a][m1][m2] = 0;
for (int i = 0; i < 10; i++){
dp[a][m1][m2] += dfs(a - 1, ((m1 - i)%K + K) % K, ((m2 - i*poww[a-1])%K + K) % K);
}
return dp[a][m1][m2];
}
int solve(int n){
if (n == 0){ return 1; }
int nn = n, num[15], tot = 0,ans=0;
while (nn != 0){
num[tot++] = nn % 10;
nn /= 10;
}
int m1 = 0, m2 = 0;
for (int i = tot - 1; i >= 0; i--){
if (i != 0){
for (int j = 0; j < num[i]; j++){
ans += dfs(i, (K - (m1 + j)%K) % K, (K - (m2 + poww[i] * j)%K)%K);
}
}
else{
for (int j = 0; j <= num[i]; j++){
ans += dfs(i, (K - (m1 + j) % K) % K, (K - (m2 + poww[i] * j) % K)%K);
}
}
m1 += num[i];
m2 += poww[i] * num[i];
}
return ans;
}
int main(){
poww[0] = 1;
for (int i = 1; i < 12; i++){ poww[i] = poww[i - 1] * 10; }
int t;
scanf("%d", &t);
while (t--){
scanf("%d%d%d", &n, &m, &K);
if (K>85)printf("0\n");
else{
memset(dp, -1, sizeof(dp));
printf("%d\n", solve(m) - solve(n - 1));
}
}
return 0;
}