依然满足区间减法,和一般的数位do没什么不同,只是要求平方和罢了。
由于 ∑(Y + xi)^2 = ∑(Y^2 + 2 * Y * xi + xi^2) = n * Y^2 + 2 * Y * ∑xi + ∑ xi^2 ,
因此dfs的时候记录三个数组:(1)f:和 7 无关的数的个数;(2)sum:和 7无关的数的和;(3)squSum:和 7无关的数的平方和即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define clr(A) memset(A,0,sizeof(A))
#define mod 1000000007
using namespace std;
LL N , M;
LL p[30];
LL f[30][8][8],sum[30][8][8],squ[30][8][8];
int num[100];
LL dfs(int l,int r1,int r2,LL &F,LL &Sum,bool e) {
if(l == -1)
{
if(r1 != 0 && r2 != 0) {F = 1 ,Sum = 0;return 0;}
return F = Sum = 0;
}
if(!e && f[l][r1][r2] != -1)
{
F = f[l][r1][r2],Sum = sum[l][r1][r2];
return squ[l][r1][r2];
}
LL res = 0,Ff = 0,Ss = 0,tmp1,tmp2;
int u = e?num[l]:9;
for(int d = 0; d <= u;d++)
if(d == 7) continue;
else {
tmp1 = dfs(l-1,(r1+d) % 7,(r2*10+d) % 7,F,Sum,e&&d==u),
tmp2 = d * p[l]% mod;
Ff = (F+Ff) % mod, Ss = (tmp2 * F + Sum +Ss) % mod,
res = (res + tmp2*tmp2%mod * F % mod + tmp2 *2 % mod * Sum % mod+tmp1) % mod;
}
F = Ff,Sum = Ss;
if(!e) f[l][r1][r2] = Ff,sum[l][r1][r2] = Ss, squ[l][r1][r2] = res;
return res;
}
LL getans(LL n){
int mm = 0;
for(; n ; n /= 10) num[mm++] = n % 10;
LL F,Sum;
return dfs(mm - 1 , 0 , 0 , F , Sum , 1) ;
}
void doit()
{
LL tmp = 1;
for(int i = 0; i <= 20; i++)
p[i] = tmp,tmp = tmp * 10 % mod;
}
void solve(){
printf("%I64d\n" , (getans(M) - getans(N-1)+mod)% mod);
}
int main(){
int T;
memset(f,-1,sizeof(f));
scanf("%d",&T);
doit();
while(T--){
scanf("%I64d%I64d",&N,&M);
solve();
}
}