题意:
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
分析:
设数位为: d l e n − 1 d l e n − 2 ⋯ d 2 d 1 d 0 d_{len-1}d_{len-2}\cdots d_2d_1d_0 dlen−1dlen−2⋯d2d1d0
- 常规的数位DP过程,可以处理出 d p [ i ] [ ⋯ ] . c n t dp[i][\cdots].cnt dp[i][⋯].cnt:后 i + 1 i+1 i+1位符合条件的数的个数;
- 先考虑处理出 d p [ i ] [ ⋯ ] . s u m dp[i][\cdots].sum dp[i][⋯].sum:后 i + 1 i+1 i+1位符合条件的数的和;
则设当前位(第i+1位)填入的数为 k k k,数位状态为: a b ⋯ k d i − 1 d i − 2 ⋯ d 2 d 1 d 0 ab\cdots kd_{i-1}d_{i-2}\cdots d_2d_1d_0 ab⋯kdi−1di−2⋯d2d1d0
对于后 i + 1 i+1 i+1位,可拆分为: k ∗ 1 0 i + d i − 1 d i − 2 ⋯ d 2 d 1 d 0 k*10^i+d_{i-1}d_{i-2}\cdots d_2d_1d_0 k∗10i+di−1di−2⋯d2d1d0
对其求和得:
k
∗
1
0
i
∗
d
p
[
i
−
1
]
[
⋯
]
.
c
n
t
+
d
p
[
i
−
1
]
[
⋯
]
.
s
u
m
k*10^i*dp[i-1][\cdots].cnt+dp[i-1][\cdots].sum
k∗10i∗dp[i−1][⋯].cnt+dp[i−1][⋯].sum
则有:
d
p
[
i
]
[
⋯
]
.
s
u
m
=
∑
k
=
0
u
p
(
上
式
)
dp[i][\cdots].sum=\displaystyle\sum_{k=0}^{up} (上式)
dp[i][⋯].sum=k=0∑up(上式)
- 最后处理 d p [ i ] [ ⋯ ] . s q s u m dp[i][\cdots].sqsum dp[i][⋯].sqsum:后 i + 1 i+1 i+1位符合条件的数的平方和;
同样地,设当前位(第i+1位)填入的数为 k k k,数位状态为: a b ⋯ k d i − 1 d i − 2 ⋯ d 2 d 1 d 0 ab\cdots kd_{i-1}d_{i-2}\cdots d_2d_1d_0 ab⋯kdi−1di−2⋯d2d1d0
对于后 i + 1 i+1 i+1位,可拆分为 k ∗ 1 0 i + d i − 1 d i − 2 ⋯ d 2 d 1 d 0 k*10^i+d_{i-1}d_{i-2}\cdots d_2d_1d_0 k∗10i+di−1di−2⋯d2d1d0
平方后得:
k
2
∗
1
0
2
i
+
2
∗
k
∗
1
0
i
∗
d
i
−
1
d
i
−
2
⋯
d
2
d
1
d
0
+
(
d
i
−
1
d
i
−
2
⋯
d
2
d
1
d
0
)
2
k^2*10^{2i}+2*k*10^i*d_{i-1}d_{i-2}\cdots d_2d_1d_0+(d_{i-1}d_{i-2}\cdots d_2d_1d_0)^2
k2∗102i+2∗k∗10i∗di−1di−2⋯d2d1d0+(di−1di−2⋯d2d1d0)2
对其求和得:
k
2
∗
1
0
2
i
∗
d
p
[
i
−
1
]
[
⋯
]
.
c
n
t
+
2
∗
k
∗
1
0
i
∗
d
p
[
i
−
1
]
[
⋯
]
.
s
u
m
+
d
p
[
i
−
1
]
[
⋯
]
.
s
q
s
u
m
k^2*10^{2i}*dp[i-1][\cdots].cnt+2*k*10^i*dp[i-1][\cdots].sum+dp[i-1][\cdots].sqsum
k2∗102i∗dp[i−1][⋯].cnt+2∗k∗10i∗dp[i−1][⋯].sum+dp[i−1][⋯].sqsum
则有:
d
p
[
i
]
[
⋯
]
.
s
q
s
u
m
=
∑
k
=
0
u
p
(
上
式
)
dp[i][\cdots].sqsum=\displaystyle\sum_{k=0}^{up} (上式)
dp[i][⋯].sqsum=k=0∑up(上式)
以下代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int maxn=1e5+10;
LL qpow(LL a,LL b)
{
LL res=1;
while(b)
{
if(b&1)
res=(res*a)%MOD;
a=(a*a)%MOD;
b>>=1;
}
return res;
}
struct Node
{
LL cnt;
LL sum;
LL sqsum;
}dp[30][10][10];
int a[30];
Node DFS(int pos,int rem1,int rem2,bool limit)
{
if(pos<0)
return Node{(rem1&&rem2)?1:0,0,0};
if(!limit&&dp[pos][rem1][rem2].cnt!=-1)
return dp[pos][rem1][rem2];
int up=limit?a[pos]:9;
Node res={0,0,0};
for(int i=0;i<=up;i++)
{
if(i==7)
continue;
Node temp=DFS(pos-1,(rem1+i)%7,(rem2*10+i)%7,limit&&i==up);
res.cnt+=temp.cnt;
res.cnt%=MOD;
res.sum+=i*qpow(10,pos)%MOD*temp.cnt%MOD+temp.sum;
res.sum%=MOD;
res.sqsum+=(i*qpow(10,pos)%MOD)*(i*qpow(10,pos)%MOD)%MOD*temp.cnt%MOD+2*i*qpow(10,pos)%MOD*temp.sum%MOD+temp.sqsum;
res.sqsum%=MOD;
}
if(!limit)
dp[pos][rem1][rem2]=res;
return res;
}
LL solve(LL x)
{
for(int i=0;i<30;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
dp[i][j][k]=Node{-1,0,0};
int len=0;
while(x)
{
a[len++]=x%10;
x/=10;
}
return DFS(len-1,0,0,true).sqsum;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL L,R;
scanf("%lld %lld",&L,&R);
printf("%lld\n",(solve(R)-solve(L-1)+MOD)%MOD);
}
return 0;
}