这道题目有三个要求
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
这三个实现起来难度不大,只需要存一个mod1表示各位数字之和除以7的余数,mod2表示数字除以7的余数
而这道题要求输出平方和
所以就需要考虑枚举当前第cnt位时,它对平方和的贡献为多少;
对于 可以把它展开为
,因此,想要计算当前位置的贡献,就需要用到后几位的平方和sqsum,数字sum,以及
,还有就是后面的方案数cnt,即A在后面出现了几次
这样就可以完成平方和的计算了
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int t,cnt;
long long a,b;
int num[20];
long long po[20];
struct node
{
long long sqsum;
long long sum;
long long cnt;
}dp[20][20][20];
node ddp(int cnt ,int mod1 ,int mod2 ,int limit)
{
if(cnt==-1)
{
node tmp;
tmp.cnt=(mod1!=0 && mod2!=0);
tmp.sum=tmp.sqsum=0;
return tmp;
}
if(!limit && dp[cnt][mod1][mod2].cnt!=-1) return dp[cnt][mod1][mod2];
int up=9;
if(limit) up=num[cnt];
node ans,temp;
ans.cnt=ans.sqsum=ans.sum=0;
for(int i=0;i<=up;i++)
{
if(i==7) continue;
temp=ddp(cnt-1,(mod1+i)%7,(mod2*10+i)%7,limit && i==up);
ans.cnt+=temp.cnt;
ans.cnt%=mod;
ans.sum+=(temp.sum+((po[cnt]*i)%mod)*temp.cnt%mod)%mod;
ans.sum%=mod;
ans.sqsum+=((temp.cnt*po[cnt])%mod*po[cnt]%mod*i*i%mod)%mod;
ans.sqsum%=mod;
ans.sqsum+=(temp.sqsum+((2*i*po[cnt])%mod)*temp.sum)%mod;
ans.sqsum%=mod;
}
if(!limit) dp[cnt][mod1][mod2]=ans;
return ans;
}
long long solve(long long x)
{
cnt=0;
while(x)
{
num[cnt++]=x%10;
x/=10;
}
return ddp(cnt-1,0,0,1).sqsum;
}
int main()
{
scanf("%d",&t);
po[0]=1;
for(int i=1;i<=20;i++)
po[i]=po[i-1]*10%mod;
while(t--)
{
memset(dp,-1,sizeof(dp));
scanf("%lld%lld",&a,&b);
long long ans=solve(b)-solve(a-1);
printf("%lld\n",(ans%mod+mod)%mod);
}
return 0;
}