题解
- 题目大意:给定一个区间,问区间内不满足以上所有条件的数的平方和
- 显然数位DP,设f[i][j][k][l]为当前枚举到第i位(从高到低),前i位是否与R的前i位相同,当前的数对A取模的余数为k,当前的数位和对A取模的余数为l的方案数
- 再设s[i][j][k][l]为这些数的和,g[i][j][k][l]为这些数的平方和
- 转移也挺简单的,我们现有状态为(i, same, mo, sum),然后枚举一个当前位置选的数ch
- 首先ch不能等于A,而且当same=1时,当前位不能大于R的当前位
- 然后就直接转移就好了,答案就是∑g[1][same][mo][sum]
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #define ll long long
5 using namespace std;
6 const ll MO=1e9+7;
7 ll n,m,ans,l,r,a,f[40][2][10][10],g[40][2][10][10],s[40][2][10][10],K[40];
8 ll calc(ll x)
9 {
10 ll p=x,tot=0; memset(K,0,sizeof(K)),memset(f,0,sizeof(f)),memset(g,0,sizeof(g)),memset(s,0,sizeof(s));
11 while (p) K[++tot]=p%10,p/=10;
12 f[tot+1][1][0][0]=1;
13 for (ll i=tot;i>=1;i--)
14 for (ll j=0;j<=1;j++)
15 for (ll mo=0;mo<=a-1;mo++)
16 for (ll sum=0;sum<=a-1;sum++)
17 if (f[i+1][j][mo][sum])
18 for (ll ch=0;ch<=9;ch++)
19 if (ch!=a&&(!(j&&ch>K[i])))
20 {
21 ll b=(j&&ch==K[i]),c=(mo*10+ch)%a,d=(sum+ch)%a;
22 f[i][b][c][d]=(f[i][b][c][d]+f[i+1][j][mo][sum])%MO;
23 s[i][b][c][d]=(s[i][b][c][d]+10ll*s[i+1][j][mo][sum]%MO+f[i+1][j][mo][sum]*ch%MO)%MO;
24 g[i][b][c][d]=(g[i][b][c][d]+100ll*g[i+1][j][mo][sum]%MO+20ll*ch*s[i+1][j][mo][sum]%MO+ch*ch*f[i+1][j][mo][sum]%MO)%MO;
25 }
26 ll ans=0;
27 for (ll j=0;j<=1;j++) for (ll mo=1;mo<=a-1;mo++) for (ll sum=1;sum<=a-1;sum++) (ans+=g[1][j][mo][sum])%=MO;
28 return ans;
29 }
30 int main()
31 {
32 scanf("%lld",&n);
33 while (n--)
34 {
35 scanf("%lld%lld%lld",&l,&r,&a);
36 printf("%lld\n",(calc(r)-calc(l-1)+MO)%MO);
37 }
38 }