题意
给你t个区间,让你求这个区间之间中不满足这三个条件之一的数的平方和。
1. S是a的倍数。
2. S在十进制表示下的各项数字加起来是a的倍数。
3. S的某一位是a
数据范围
对于15%的数据,
0<=L<=R<=106,T=1
对于35%的数据,
0<=L<=R<=107,T=1
另外有25%的数据,
A=2,L=10k,R=10v,
k和v都是自然数。
对于100%的数据,
0<=L<=R<=1018,2<=A<=9,T<=100
分析
一看就明显的
数位dp
,考试后还是第一次听说这个东东,所以就恶补了一下数位
dp
。。
首先按照惯例,我们要设一个
f[i,same,mo,sum]
表示枚举到第i位数(从高到低),前面i位是否与右边界相同(为了方便统计答案),前面i位组成的数对
a
取模的数,前面i位各个位加起来的和对
转移方程
转移很简单,我们先讨论f的转移:枚举第i+1位的数是多少ch,那么转移到第i+1位就是
f[i+1,sameand(bit[i+1]=ch),(mo∗10+ch)modA,(sum+ch)modA]+=f[i,same,mo,sum](ch<>a,当same=1,ch<=bit[i+1])
g的转移也是类似的:
g[i+1,sameand(bit[i+1]=ch),(mo∗10+ch)modA,(sum+ch)modA]+=g[i,same,mo,sum]∗10+ch∗f[i,same,mo,sum](ch<>a,当same=1,ch<=bit[i+1])
s的转移麻烦一点:
我们可以这样理解:(设
ai
表示当前的满足条件的数,现在要加上ch)
(a1∗10+ch)2+(a2∗10+ch)2+(a3∗10+ch)2......
(a12∗100+ch2+20∗ch∗a1)+(a22∗100+ch2+20∗ch∗a2)+(a32∗100+ch2+20∗ch∗a3)......
合并
a1+a2+a3...
->
g[i,same,mo,sum]
合并
a12+a22+a32....
->
s[i,same,mo,sum]
合并
ch2+ch2+ch2.....
->
f[i,same,mo,sum]∗ch2
那么这样原式变成
s[i,same,mo,sum]∗100+f[i,same,mo,sum]∗ch2+g[i,same,mo,sum]∗ch∗20
所以转移方程为:
s[i+1,sameand(bit[i+1]=ch),(mo∗10+ch)modA,(sum+ch)modA]+=s[i,same,mo,sum]∗100+f[i,same,mo,sum]∗ch2+g[i,same,mo,sum]∗ch∗20(ch<>a,当same=1,ch<=bit[i+1])
最后再统计
mo<>0,sum<>0
的s即可
时间复杂度:
O(T∗logR∗2∗103)
这样便可以很好的解决问题了。
代码:(我是顺推的,所以初始化有点猥琐。。)
const m=1000000007;
var
g,f,s:array[0..20,0..1,0..9,0..9] of int64;
i,t,a:longint;l,r:int64;
procedure vare(var x:int64);begin if x=-1 then x:=0;end;
procedure sets(var x:longint;y:longint);
begin x:=(x+y)mod m;end;
procedure sets(i,p,mo,sum,i1,p1,mo1,sum1,k:longint);
begin
vare(f[i,p,mo,sum]);vare(g[i,p,mo,sum]);vare(s[i,p,mo,sum]);
f[i,p,mo,sum]:=(f[i,p,mo,sum]+f[i1,p1,mo1,sum1])mod m;
g[i,p,mo,sum]:=(100*g[i1,p1,mo1,sum1]+20*k*s[i1,p1,mo1,sum1]+k*k*f[i1,p1,mo1,sum1]+g[i,p,mo,sum])mod m;
s[i,p,mo,sum]:=(s[i1,p1,mo1,sum1]*10+k*f[i1,p1,mo1,sum1]+s[i,p,mo,sum])mod m;
end;
function solve(x,y:int64):int64;
var i,j,mo,sum,ch,t,o,p:longint;bit,ti:array[0..100] of integer;ans:int64;
begin
if x=0 then exit(0);
fillchar(f,sizeof(f),255);
fillchar(g,sizeof(g),255);
fillchar(s,sizeof(s),255);
o:=0;
while x<>0 do begin
inc(o);bit[o]:=x mod 10;x:=x div 10;
end;for i:=1 to o do ti[i]:=bit[o-i+1];bit:=ti;
for i:=0 to bit[1] do if y<>i then begin
if i=bit[1] then t:=1 else t:=0;
vare(g[1,t,i mod y,i mod y]);vare(f[1,t,i mod y,i mod y]);vare(s[1,t,i mod y,i mod y]);
inc(g[1,t,i mod y,i mod y],i*i);
inc(f[1,t,i mod y,i mod y],1);
inc(s[1,t,i mod y,i mod y],i);
end;
for i:=1 to o-1 do
for p:=0 to 1 do
for ch:=0 to 9 do if (p=1)and(bit[i+1]<ch) then break
else begin
if ch=y then continue;
for mo:=0 to y do
for sum:=0 to y do begin
if f[i,p,mo,sum]=-1 then continue;
if (p=1)and(ch=bit[i+1]) then t:=1 else t:=0;
if ch=5 then
o:=o;
sets(i+1,t,(mo*10+ch)mod y,(sum+ch)mod y,i,p,mo,sum,ch);
end;
end;ans:=0;
for p:=0 to 1 do
for mo:=0 to y do
for sum:=0 to y do
if (g[o,p,mo,sum]<>-1)and(sum<>0)and(mo<>0) then
ans:=(ans+g[o,p,mo,sum])mod m;
exit(ans);
end;
begin
readln(t);
for t:=1 to t do begin
readln(l,r,a);
writeln((solve(r,a)-solve(l-1,a)+m)mod m);
end;
end.