NOI2013矩阵游戏
Description
婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式:
F[1][1]=1
F[i,j]=a*F[i][j-1]+b (j!=1)
F[i,1]=c*F[i-1][m]+d (i!=1)
递推式中a,b,c,d都是给定的常数。
现在婷婷想知道F[n][m]的值是多少,请你帮助她。由于最终结果可能很大,你只需要输出F[n][m]除以1,000,000,007的余数。
Input
一行有六个整数n,m,a,b,c,d。意义如题所述
Output
包含一个整数,表示F[n][m]除以1,000,000,007的余数
Sample Input
3 4 1 3 2 6
Sample Output
85
HINT
样例中的矩阵为:
1 4 7 10
26 29 32 35
76 79 82 85
题解:
不看数据范围的话这就是到水题……
前10个点很好过,普通的二进制快速幂就可以
后面10个点如果还用原来的方法,需要涉及高精度除以单精度,复杂度是O(len)的
所以一种新的快速幂诞生了!-----十进制快速幂!
(转)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再举个例子吧...
1 const p=1000000007; 2 type matrix=array[1..2,1..2] of longint; 3 var a,b,c:matrix; 4 i,n,m,a1,a2,b1,b2:longint; 5 procedure mul(var x,y,z:matrix); 6 var t:matrix; 7 i,j,k:longint; 8 begin 9 fillchar(t,sizeof(t),0); 10 for i:=1 to 2 do 11 for j:=1 to 2 do 12 for k:=1 to 2 do 13 t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p; 14 z:=t; 15 end; 16 procedure ksm(cs:longint); 17 begin 18 while cs>0 do 19 begin 20 if cs and 1=1 then mul(a,b,b); 21 cs:=cs>>1; 22 mul(a,a,a); 23 end; 24 end; 25 procedure init; 26 begin 27 readln(n,m,a1,b1,a2,b2); 28 end; 29 procedure main; 30 begin 31 a[1,1]:=1;a[1,2]:=b1;a[2,1]:=0;a[2,2]:=a1; 32 for i:=1 to 2 do b[i,i]:=1; 33 ksm(m-1); 34 c:=b; 35 b[1,1]:=1;b[1,2]:=b2;b[2,1]:=0;b[2,2]:=a2; 36 mul(c,b,a); 37 fillchar(b,sizeof(b),0); 38 for i:=1 to 2 do b[i,i]:=1; 39 ksm(n-1); 40 mul(b,c,b); 41 writeln((b[1,2]+b[2,2]) mod p); 42 end; 43 begin 44 init; 45 main; 46 end.
代码2:80分 十进制快速幂(后四个点TLE)
1 const p=1000000007; 2 type matrix=array[1..2,1..2] of longint; 3 arrtype=array[0..1500000] of longint; 4 var a,b,c:matrix; 5 mm:array[0..9] of matrix; 6 i,a1,a2,b1,b2:longint; 7 n,m:arrtype; 8 ch:char; 9 procedure mul(var x,y,z:matrix); 10 var t:matrix; 11 i,j,k:longint; 12 begin 13 fillchar(t,sizeof(t),0); 14 for i:=1 to 2 do 15 for j:=1 to 2 do 16 for k:=1 to 2 do 17 t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p; 18 z:=t; 19 end; 20 procedure pow10(s:arrtype); 21 var i,j:longint;t:matrix; 22 begin 23 dec(s[s[0]]);i:=s[0];while s[i]<0 do begin inc(s[i],10);dec(s[i-1],1);dec(i);end; 24 fillchar(mm,sizeof(mm),0); 25 for i:=1 to 2 do mm[0,i,i]:=1; 26 for i:=1 to 9 do mul(mm[i-1],a,mm[i]); 27 fillchar(b,sizeof(b),0); 28 for i:=1 to 2 do b[i,i]:=1; 29 for i:=1 to s[0] do 30 begin 31 mul(b,mm[s[i]],b); 32 if i=s[0] then break; 33 t:=b; 34 for j:=2 to 10 do mul(b,t,b); 35 end; 36 end; 37 procedure init; 38 begin 39 read(ch);n[0]:=0; 40 while ch<>' ' do 41 begin 42 inc(n[0]);n[n[0]]:=ord(ch)-ord('0'); 43 read(ch); 44 end; 45 read(ch);m[0]:=0; 46 while ch<>' ' do 47 begin 48 inc(m[0]);m[m[0]]:=ord(ch)-ord('0'); 49 read(ch); 50 end; 51 readln(a1,b1,a2,b2); 52 end; 53 procedure main; 54 begin 55 a[1,1]:=1;a[1,2]:=b1;a[2,1]:=0;a[2,2]:=a1; 56 pow10(m); 57 c:=b; 58 b[1,1]:=1;b[1,2]:=b2;b[2,1]:=0;b[2,2]:=a2; 59 mul(c,b,a); 60 pow10(n); 61 mul(b,c,b); 62 writeln((b[1,2]+b[2,2]) mod p); 63 end; 64 begin 65 init; 66 main; 67 end.
代码3:80分 考虑把代码二中 ans^10换成二进制快速幂(依然TLE)
1 const p=1000000007; 2 type matrix=array[1..2,1..2] of int64; 3 arrtype=array[0..1500000] of longint; 4 var a,b,c:matrix; 5 mm:array[0..9] of matrix; 6 i,a1,a2,b1,b2:longint; 7 n,m:arrtype; 8 ch:char; 9 procedure mul(var x,y,z:matrix); 10 var t:matrix; 11 i,j,k:longint; 12 begin 13 fillchar(t,sizeof(t),0); 14 for i:=1 to 2 do 15 for j:=1 to 2 do 16 for k:=1 to 2 do 17 t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p; 18 z:=t; 19 end; 20 procedure pow10(s:arrtype); 21 var i,j,cs:longint;tmp:matrix; 22 begin 23 dec(s[s[0]]);i:=s[0];while s[i]<0 do begin inc(s[i],10);dec(s[i-1],1);dec(i);end; 24 fillchar(mm,sizeof(mm),0); 25 for i:=1 to 2 do mm[0,i,i]:=1; 26 for i:=1 to 9 do mul(mm[i-1],a,mm[i]); 27 fillchar(b,sizeof(b),0); 28 for i:=1 to 2 do b[i,i]:=1; 29 for i:=1 to s[0] do 30 begin 31 mul(b,mm[s[i]],b); 32 if i=s[0] then break; 33 tmp:=b; 34 fillchar(b,sizeof(b),0); 35 for j:=1 to 2 do b[j,j]:=1; 36 cs:=10; 37 while cs>0 do 38 begin 39 if cs and 1=1 then mul(tmp,b,b); 40 cs:=cs>>1; 41 mul(tmp,tmp,tmp); 42 end; 43 end; 44 end; 45 procedure init; 46 begin 47 read(ch);n[0]:=0; 48 while ch<>' ' do 49 begin 50 inc(n[0]);n[n[0]]:=ord(ch)-ord('0'); 51 read(ch); 52 end; 53 read(ch);m[0]:=0; 54 while ch<>' ' do 55 begin 56 inc(m[0]);m[m[0]]:=ord(ch)-ord('0'); 57 read(ch); 58 end; 59 readln(a1,b1,a2,b2); 60 end; 61 procedure main; 62 begin 63 a[1,1]:=1;a[1,2]:=b1;a[2,1]:=0;a[2,2]:=a1; 64 pow10(m); 65 c:=b; 66 b[1,1]:=1;b[1,2]:=b2;b[2,1]:=0;b[2,2]:=a2; 67 mul(c,b,a); 68 pow10(n); 69 mul(b,c,b); 70 writeln((b[1,2]+b[2,2]) mod p); 71 end; 72 begin 73 init; 74 main; 75 end.
代码4:受兰多夫87的影响,考虑修改矩阵乘法,应为第一列始终是不变的 (为什么还是TLE啊…………)
1 const p=1000000007; 2 type matrix=array[1..2,1..2] of int64; 3 arrtype=array[0..1500000] of longint; 4 var a,b,c:matrix; 5 mm:array[0..9] of matrix; 6 i,a1,a2,b1,b2:longint; 7 n,m:arrtype; 8 ch:char; 9 procedure mul(var x,y,z:matrix); 10 var t:matrix; 11 i,j,k:longint; 12 begin 13 fillchar(t,sizeof(t),0); 14 t[1,1]:=1;t[2,1]:=0; 15 for i:=1 to 2 do 16 for k:=1 to 2 do 17 t[i,2]:=(t[i,2]+x[i,k]*y[k,2]) mod p; 18 z:=t; 19 end; 20 procedure pow10(s:arrtype); 21 var i,j,cs:longint;tmp:matrix; 22 begin 23 dec(s[s[0]]);i:=s[0];while s[i]<0 do begin inc(s[i],10);dec(s[i-1],1);dec(i);end; 24 fillchar(mm,sizeof(mm),0); 25 for i:=1 to 2 do mm[0,i,i]:=1; 26 for i:=1 to 9 do mul(mm[i-1],a,mm[i]); 27 fillchar(b,sizeof(b),0); 28 for i:=1 to 2 do b[i,i]:=1; 29 for i:=1 to s[0] do 30 begin 31 mul(b,mm[s[i]],b); 32 if i=s[0] then break; 33 tmp:=b; 34 fillchar(b,sizeof(b),0); 35 for j:=1 to 2 do b[j,j]:=1; 36 cs:=10; 37 while cs>0 do 38 begin 39 if cs and 1=1 then mul(tmp,b,b); 40 cs:=cs>>1; 41 mul(tmp,tmp,tmp); 42 end; 43 end; 44 end; 45 procedure init; 46 begin 47 read(ch);n[0]:=0; 48 while ch<>' ' do 49 begin 50 inc(n[0]);n[n[0]]:=ord(ch)-ord('0'); 51 read(ch); 52 end; 53 read(ch);m[0]:=0; 54 while ch<>' ' do 55 begin 56 inc(m[0]);m[m[0]]:=ord(ch)-ord('0'); 57 read(ch); 58 end; 59 readln(a1,b1,a2,b2); 60 end; 61 procedure main; 62 begin 63 a[1,1]:=1;a[1,2]:=b1;a[2,1]:=0;a[2,2]:=a1; 64 pow10(m); 65 c:=b; 66 b[1,1]:=1;b[1,2]:=b2;b[2,1]:=0;b[2,2]:=a2; 67 mul(c,b,a); 68 pow10(n); 69 mul(b,c,b); 70 writeln((b[1,2]+b[2,2]) mod p); 71 end; 72 begin 73 init; 74 main; 75 end. 76
代码5:我认为是我写丑了 膜拜兰多夫87吧
1 const p=1000000007; 2 type matrix=array[1..2] of int64; 3 arrtype=array[0..1500000] of longint; 4 var x,y:matrix; 5 z:array[0..9] of matrix; 6 i,a,b,c,d:longint; 7 n,m:arrtype; 8 ch:char; 9 operator *(a,b:matrix)c:matrix; 10 begin 11 c[1]:=a[1]*b[1] mod p; 12 c[2]:=(b[1]*a[2]+b[2]) mod p; 13 end; 14 function f(x:matrix;var a:arrtype):matrix; 15 var i:longint;y:matrix; 16 begin 17 dec(a[a[0]]);i:=a[0]; 18 while a[i]<0 do begin inc(a[i],10);dec(a[i-1]);dec(i);end; 19 z[0,1]:=1;z[0,2]:=0; 20 for i:=1 to 9 do z[i]:=z[i-1]*x; 21 x:=z[0]; 22 for i:=1 to a[0] do 23 begin 24 y:=x*x; 25 x:=x*y*y; 26 x:=x*x; 27 x:=x*z[a[i]]; 28 end; 29 exit(x); 30 end; 31 procedure init; 32 begin 33 read(ch);n[0]:=0; 34 while ch<>' ' do 35 begin 36 inc(n[0]);n[n[0]]:=ord(ch)-ord('0'); 37 read(ch); 38 end; 39 read(ch);m[0]:=0; 40 while ch<>' ' do 41 begin 42 inc(m[0]);m[m[0]]:=ord(ch)-ord('0'); 43 read(ch); 44 end; 45 readln(a,b,c,d); 46 end; 47 procedure main; 48 begin 49 x[1]:=a;x[2]:=b; 50 x:=f(x,m); 51 y[1]:=c;y[2]:=d; 52 y:=x*y; 53 y:=f(y,n); 54 y:=y*x; 55 writeln((y[1]+y[2]) mod p); 56 end; 57 begin 58 assign(input,'matrix.in');assign(output,'matrix.out'); 59 reset(input);rewrite(output); 60 init; 61 main; 62 close(input);close(output); 63 end.
无限orz!
看来养成一个好的代码风格是必要的