各位数之和不会超过100,所以 k > 100 时直接输出0 。
dp[a][b][c] 表示有a位未知,未知各位之和除以K的余数为b,未知位组成的数字除以K的余数位c的个数。
#include <iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
int a[15],num[15];
int dp[15][100][100];
int K;
void prework()
{
a[0] = 1;
for(int i = 1;i < 10;i++) a[i] = a[i - 1]*10;
memset(dp,0,sizeof dp);
for(int i = 0;i < 10;i++) dp[1][i%K][i%K]++;
for(int i = 2;i <= 10;i++) //未知的位数
for(int j = 0;j < K;j++) //枚举各位之和除以K的余数
for(int kk = 0;kk < K;kk++) //枚举数字除以K的余数
for(int l = 0;l < 10;l++) //枚举最低位
dp[i][(j+l)%K][((kk*10)%K+l)%K] += dp[i-1][j][kk];
}
int calc(int x)
{
int ans = 0;
if(x == 0) return 1;
int cnt = 0;
while(x) //num存读入的每一位数
{
num[++cnt] = x%10;
x/=10;
}
int m1 = 0,m2 = 0;
//cnt是一共几位数
for(int i = cnt;i >= 2;i--)
{
for(int j = 0;j < num[i];j++)
{
int k1 = ((m1 - j)%K + K)%K;
int k2 = ((m2 - a[i-1]*j%K)%K+K)%K;
//公式见白书,m1:已确定的位数之和模K m2:已确定的数模K
ans+=dp[i-1][k1][k2];
}
//固定第i位
m1 = ((m1 - num[i])%K + K)%K;
m2 = ((m2 - num[i]*a[i-1]%K)%K+K)%K;
}
//枚举个位
for(int i = 0 ; i <= num[1];i++)
if(i%K == m1 && i%K == m2) ans++;
return ans;
}
int main()
{
int t,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d %d %d",&a,&b,&K);
if(K > 100) printf("0\n");
else
{
prework();
printf("%d\n",calc(b)-calc(a-1));
}
}
return 0;
}