BZOJ2326: [HNOI2011]数学作业
2326: [HNOI2011]数学作业
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 955 Solved: 535
[Submit][Status]
Description
题解:
第一次知道矩阵乘法还能这样用,真是太神了!
我想到了递推式:
f[i]=(f[i-1]*10^len[i]+i) mod p
但是我没有办法用矩阵乘法来解决这样 f[i]=a*f[i-1]+b 但a和b都随着 i 的变化而变化
可以分位数来消掉a的变化,但是b我无法解决。
看了题解之后发现居然还可以这样!
把矩阵增一维
(f[i-1],i-1,1)*(10^len(i),0 0 =(f[i],i,1)
1,1,0
1,1,1)
简直太神了!原来矩阵不仅可以快速求解 线性递推式,还可以求解这样的,只要把变化的量一同加入矩阵的表示中即可。
题外话:
不会写 c++ 的矩阵快速幂,只好上pascal了。。。
边界要注意,想清楚了再写。
矩阵满足结合律,不满足交换律。
代码:
1 type matrix=array[1..3,1..3] of int64; 2 var a,b,c:matrix; 3 m:array[0..18] of int64; 4 i,j:longint; 5 cs,n,p:int64; 6 s:string; 7 operator *(a,b:matrix)c:matrix; 8 var i,j,k:longint; 9 begin 10 fillchar(c,sizeof(c),0); 11 for i:=1 to 3 do 12 for j:=1 to 3 do 13 for k:=1 to 3 do 14 c[i,j]:=(c[i,j]+(a[i,k]*b[k,j] mod p)) mod p; 15 end; 16 procedure main; 17 begin 18 m[0]:=1; 19 for i:=1 to 18 do m[i]:=m[i-1]*10; 20 readln(n,p);str(n,s); 21 fillchar(b,sizeof(b),0); 22 for i:=1 to 3 do b[i,i]:=1; 23 for i:=1 to length(s) do 24 begin 25 if i<>length(s) then cs:=m[i]-m[i-1] else cs:=n-m[length(s)-1]+1; 26 a[1,1]:=m[i] mod p;a[1,2]:=0;a[1,3]:=0; 27 a[2,1]:=1;a[2,2]:=1;a[2,3]:=0; 28 a[3,1]:=1;a[3,2]:=1;a[3,3]:=1; 29 while cs>0 do 30 begin 31 if cs and 1=1 then b:=b*a; 32 cs:=cs>>1; 33 a:=a*a; 34 end; 35 end; 36 writeln(b[3,1]); 37 end; 38 39 begin 40 assign(input,'input.txt');assign(output,'output.txt'); 41 reset(input);rewrite(output); 42 main; 43 close(input);close(output); 44 end.