首页 > 代码库 > BZOJ2326: [HNOI2011]数学作业

BZOJ2326: [HNOI2011]数学作业

2326: [HNOI2011]数学作业

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 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  begin10    fillchar(c,sizeof(c),0);11    for i:=1 to 3 do12     for j:=1 to 3 do13      for k:=1 to 3 do14       c[i,j]:=(c[i,j]+(a[i,k]*b[k,j] mod p)) mod p;15  end;16 procedure main;17  begin18    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) do24     begin25      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 do30       begin31        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 begin40   assign(input,input.txt);assign(output,output.txt);41   reset(input);rewrite(output);42   main;43   close(input);close(output);44 end.   
View Code

 

 

BZOJ2326: [HNOI2011]数学作业