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

NOI2013矩阵游戏

题解:

不看数据范围的话这就是到水题……

前10个点很好过,普通的二进制快速幂就可以  

后面10个点如果还用原来的方法,需要涉及高精度除以单精度,复杂度是O(len)的

所以一种新的快速幂诞生了!-----十进制快速幂!

(转)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

假设咱们需要求 m^n,咱们有一种方法是 二进制快速幂,这个的复杂度是O(logn)的。但是咱们还可以做的更好实际上....咱们把 n拆成10进制表达式,比如 :
234=2*10^2+3*10+4,
139476=1*10^5+3*10^4+9*10^3+4*10^2+7*10^1+6
咱们设拆成的形式是
n=a0+a1*10^1+a2*10^2...+ai*10^i+...+ad*10^d,d为n的最高位,其实就是d=【logn】(log以10为底数)
然后这个表示出来了咱们有:
m^n=m^(a0+a1*10^1+a2*10^2+...+ai*10^i...+ad*10^d)(ak∈【0,9】,k∈【1,d】)
看出一点来了吧...
咱们可以化成 m^n=m^a9*(m^a1)^10*(m^a2)^100....
继续化简,咱们有 m^n=(((m^ad)^10*ad-1)^10*m^ad-2).....
这个实际上就很好做了,由于 0<=ai<=9,只需要预处理下m^0~m^9即可很快计算出m^ai,然后这个就是O(logn)的,(log以10为底),只不过需要加个10的常数,不过这个的效率在n达到10^100就可以体现了=w=。
即算法流程就是初始化ans=1,从n的最高位开始,每一次提取一位w,用ans乘以m^w然后再做10次的幂,重复到n的所有位都取完了即可。即这个算法的复杂度只与n的位数有关,预处理10个数复杂度也不是很高。
然后取最高位只需要一开始分解每个位存在一个数组里面即可,这里假设是a[],然后预处理的m^0~9在mm[]里,下面就是伪代码:
 

 

function quickmod(n:int64):int64;
begin
    len=0;tmp=n
    while tmp!=0 do
        len=len+1
       a[len]=tmp mod 10;
       tmp=tmp div 10;
    ans=1
    for i=len downto 1 do
      ans=ans*mm[a[i]]
      ans=ans^10
    return ans
end
    

再举个例子吧...

比如 2^154,咱们就有 2^154=((2^1)^10*2^5)^10*2^4 咱们拆开来自然可以检验出这个是不是正确的了。
再比如 2^1512526,咱们就有
2^1512526=((((((2^1)^10*2^5)^10*2^1)^10*2^2)^10*2^5)^10*2^2)^10*2^6
为什么要用十进制快速幂?显然可以发现它的表示实际上比二进制更自然吧...每次只需要取最高位就可以了而不需要考虑什么二进制的原理,显然是十分方便的。而且复杂度比二进制的复杂度更小,还是非常不错了。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我觉得其实十进制快速幂的思想和霍纳法则(或者称之为秦九韶算法)差不多……
代码1:50分 二进制快速幂
 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.
View Code

代码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.
View Code

相关文章:

  • 2021-10-15
  • 2022-12-23
  • 2022-12-23
  • 2021-07-26
  • 2021-08-22
  • 2021-11-29
  • 2021-08-13
  • 2021-07-25
猜你喜欢
  • 2021-11-09
  • 2022-12-23
  • 2022-12-23
  • 2022-01-11
  • 2022-01-31
相关资源
相似解决方案