【题目大意】
求123456789101112131415……n构成的数mod m的值。
【基本思路】
我一开始用的是模拟,用一个字符串保存数字,再取模。这样显然超时,只能过一两个点。
后来才知道是用动态规划写的,方程是P(i)=P(i-1)*10^k+ i .
当然,直接动态规划的话效果也不好,所以我们用矩阵加速动归。
【矩阵构造】
我一开始是用别人的矩阵,也不知道原理。后来自己用草稿纸算,找到一个规律,并发现以前的矩阵有问题,所以才做错了的,于是我修改矩阵之后就AC了。
【具体做法】
设3*3矩阵Bas[i]={{10^k,0,0},{1,1,0},{1,1,1}}
答案矩阵Ans=Bas[1]^9 * bas[2]^90 * bas[3]^900 *…*bas[k]^t (10k<=t<10k+1);
Answer=Ans[3][1]
由于矩阵有二分幂算法和乘法结合率,我们可以先二分出bas[i]^k再做几次矩阵乘法就可以了。
【我的程序】
type
mat=array[1..3,1..3]of qword;
var
n,m:qword; i,j:longint;
base,ans,c:mat; dk,dt,dp:qword;
function mul(a,b:mat):mat; //矩阵乘法
var i,j,k:longint; sum:qword; c:mat;
begin
for i:=1 to 3 do for j:=1 to 3 do mul[i,j]:=0;
for i:=1 to 3 do
for j:=1 to 3 do
for k:=1 to 3 do
mul[i,j]:=(mul[i,j]+a[i,k]*b[k,j] mod m) mod m;
end;
Function muls(var b:mat;t:qword):mat; //二分快速幂
var d:mat;
begin
if t=1 then exit(b);
muls:=muls(b,t div 2);
muls:=mul(muls,muls);
if odd(t) then exit(mul(muls,b)) else exit(muls);
end;
begin
assign(input,'input.txt'); assign(output,'output.txt');
reset(input); rewrite(output);
readln(n,m);
base[2][1]:=1; base[2][2]:=1; base[3][2]:=1; base[3][3]:=1;
base[1][1]:=1; base[3][1]:=1; //构造基本矩阵
ans[1,1]:=1; ans[2,2]:=1; ans[3,3]:=1;
dk:=1; dt:=9; dp:=0;
while true do
begin
dk:= dk*10;
c:=base; c[1,1]:=dk mod m; //修改基本矩阵
if n<dk then
begin
c:=muls(c,n-dp);
ans:=mul(ans,c);
break;
end
else
begin
c:=muls(c,dt);
ans:=mul(ans,c);
dp:=dk-1;
dt:=dt*10;
end;
end;
writeln(ans[3,1]);
close(input); close(output);
end.