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)的

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

(转)

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

假设咱们需要求 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分 二进制快速幂
 const p=;
type matrix=array[..,..] of longint;
var a,b,c:matrix;
i,n,m,a1,a2,b1,b2:longint;
procedure mul(var x,y,z:matrix);
var t:matrix;
i,j,k:longint;
begin
fillchar(t,sizeof(t),);
for i:= to do
for j:= to do
for k:= to do
t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p;
z:=t;
end;
procedure ksm(cs:longint);
begin
while cs> do
begin
if cs and = then mul(a,b,b);
cs:=cs>>;
mul(a,a,a);
end;
end;
procedure init;
begin
readln(n,m,a1,b1,a2,b2);
end;
procedure main;
begin
a[,]:=;a[,]:=b1;a[,]:=;a[,]:=a1;
for i:= to do b[i,i]:=;
ksm(m-);
c:=b;
b[,]:=;b[,]:=b2;b[,]:=;b[,]:=a2;
mul(c,b,a);
fillchar(b,sizeof(b),);
for i:= to do b[i,i]:=;
ksm(n-);
mul(b,c,b);
writeln((b[,]+b[,]) mod p);
end;
begin
init;
main;
end.

代码2:80分 十进制快速幂(后四个点TLE)

 const p=;
type matrix=array[..,..] of longint;
arrtype=array[..] of longint;
var a,b,c:matrix;
mm:array[..] of matrix;
i,a1,a2,b1,b2:longint;
n,m:arrtype;
ch:char;
procedure mul(var x,y,z:matrix);
var t:matrix;
i,j,k:longint;
begin
fillchar(t,sizeof(t),);
for i:= to do
for j:= to do
for k:= to do
t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p;
z:=t;
end;
procedure pow10(s:arrtype);
var i,j:longint;t:matrix;
begin
dec(s[s[]]);i:=s[];while s[i]< do begin inc(s[i],);dec(s[i-],);dec(i);end;
fillchar(mm,sizeof(mm),);
for i:= to do mm[,i,i]:=;
for i:= to do mul(mm[i-],a,mm[i]);
fillchar(b,sizeof(b),);
for i:= to do b[i,i]:=;
for i:= to s[] do
begin
mul(b,mm[s[i]],b);
if i=s[] then break;
t:=b;
for j:= to do mul(b,t,b);
end;
end;
procedure init;
begin
read(ch);n[]:=;
while ch<>' ' do
begin
inc(n[]);n[n[]]:=ord(ch)-ord('');
read(ch);
end;
read(ch);m[]:=;
while ch<>' ' do
begin
inc(m[]);m[m[]]:=ord(ch)-ord('');
read(ch);
end;
readln(a1,b1,a2,b2);
end;
procedure main;
begin
a[,]:=;a[,]:=b1;a[,]:=;a[,]:=a1;
pow10(m);
c:=b;
b[,]:=;b[,]:=b2;b[,]:=;b[,]:=a2;
mul(c,b,a);
pow10(n);
mul(b,c,b);
writeln((b[,]+b[,]) mod p);
end;
begin
init;
main;
end.

代码3:80分 考虑把代码二中 ans^10换成二进制快速幂(依然TLE)

 const p=;
type matrix=array[..,..] of int64;
arrtype=array[..] of longint;
var a,b,c:matrix;
mm:array[..] of matrix;
i,a1,a2,b1,b2:longint;
n,m:arrtype;
ch:char;
procedure mul(var x,y,z:matrix);
var t:matrix;
i,j,k:longint;
begin
fillchar(t,sizeof(t),);
for i:= to do
for j:= to do
for k:= to do
t[i,j]:=(t[i,j]+x[i,k]*y[k,j]) mod p;
z:=t;
end;
procedure pow10(s:arrtype);
var i,j,cs:longint;tmp:matrix;
begin
dec(s[s[]]);i:=s[];while s[i]< do begin inc(s[i],);dec(s[i-],);dec(i);end;
fillchar(mm,sizeof(mm),);
for i:= to do mm[,i,i]:=;
for i:= to do mul(mm[i-],a,mm[i]);
fillchar(b,sizeof(b),);
for i:= to do b[i,i]:=;
for i:= to s[] do
begin
mul(b,mm[s[i]],b);
if i=s[] then break;
tmp:=b;
fillchar(b,sizeof(b),);
for j:= to do b[j,j]:=;
cs:=;
while cs> do
begin
if cs and = then mul(tmp,b,b);
cs:=cs>>;
mul(tmp,tmp,tmp);
end;
end;
end;
procedure init;
begin
read(ch);n[]:=;
while ch<>' ' do
begin
inc(n[]);n[n[]]:=ord(ch)-ord('');
read(ch);
end;
read(ch);m[]:=;
while ch<>' ' do
begin
inc(m[]);m[m[]]:=ord(ch)-ord('');
read(ch);
end;
readln(a1,b1,a2,b2);
end;
procedure main;
begin
a[,]:=;a[,]:=b1;a[,]:=;a[,]:=a1;
pow10(m);
c:=b;
b[,]:=;b[,]:=b2;b[,]:=;b[,]:=a2;
mul(c,b,a);
pow10(n);
mul(b,c,b);
writeln((b[,]+b[,]) mod p);
end;
begin
init;
main;
end.

代码4:受兰多夫87的影响,考虑修改矩阵乘法,应为第一列始终是不变的  (为什么还是TLE啊…………)

 const p=;
type matrix=array[..,..] of int64;
arrtype=array[..] of longint;
var a,b,c:matrix;
mm:array[..] of matrix;
i,a1,a2,b1,b2:longint;
n,m:arrtype;
ch:char;
procedure mul(var x,y,z:matrix);
var t:matrix;
i,j,k:longint;
begin
fillchar(t,sizeof(t),);
t[,]:=;t[,]:=;
for i:= to do
for k:= to do
t[i,]:=(t[i,]+x[i,k]*y[k,]) mod p;
z:=t;
end;
procedure pow10(s:arrtype);
var i,j,cs:longint;tmp:matrix;
begin
dec(s[s[]]);i:=s[];while s[i]< do begin inc(s[i],);dec(s[i-],);dec(i);end;
fillchar(mm,sizeof(mm),);
for i:= to do mm[,i,i]:=;
for i:= to do mul(mm[i-],a,mm[i]);
fillchar(b,sizeof(b),);
for i:= to do b[i,i]:=;
for i:= to s[] do
begin
mul(b,mm[s[i]],b);
if i=s[] then break;
tmp:=b;
fillchar(b,sizeof(b),);
for j:= to do b[j,j]:=;
cs:=;
while cs> do
begin
if cs and = then mul(tmp,b,b);
cs:=cs>>;
mul(tmp,tmp,tmp);
end;
end;
end;
procedure init;
begin
read(ch);n[]:=;
while ch<>' ' do
begin
inc(n[]);n[n[]]:=ord(ch)-ord('');
read(ch);
end;
read(ch);m[]:=;
while ch<>' ' do
begin
inc(m[]);m[m[]]:=ord(ch)-ord('');
read(ch);
end;
readln(a1,b1,a2,b2);
end;
procedure main;
begin
a[,]:=;a[,]:=b1;a[,]:=;a[,]:=a1;
pow10(m);
c:=b;
b[,]:=;b[,]:=b2;b[,]:=;b[,]:=a2;
mul(c,b,a);
pow10(n);
mul(b,c,b);
writeln((b[,]+b[,]) mod p);
end;
begin
init;
main;
end.

代码5:我认为是我写丑了 膜拜兰多夫87吧

 const p=;
type matrix=array[..] of int64;
arrtype=array[..] of longint;
var x,y:matrix;
z:array[..] of matrix;
i,a,b,c,d:longint;
n,m:arrtype;
ch:char;
operator *(a,b:matrix)c:matrix;
begin
c[]:=a[]*b[] mod p;
c[]:=(b[]*a[]+b[]) mod p;
end;
function f(x:matrix;var a:arrtype):matrix;
var i:longint;y:matrix;
begin
dec(a[a[]]);i:=a[];
while a[i]< do begin inc(a[i],);dec(a[i-]);dec(i);end;
z[,]:=;z[,]:=;
for i:= to do z[i]:=z[i-]*x;
x:=z[];
for i:= to a[] do
begin
y:=x*x;
x:=x*y*y;
x:=x*x;
x:=x*z[a[i]];
end;
exit(x);
end;
procedure init;
begin
read(ch);n[]:=;
while ch<>' ' do
begin
inc(n[]);n[n[]]:=ord(ch)-ord('');
read(ch);
end;
read(ch);m[]:=;
while ch<>' ' do
begin
inc(m[]);m[m[]]:=ord(ch)-ord('');
read(ch);
end;
readln(a,b,c,d);
end;
procedure main;
begin
x[]:=a;x[]:=b;
x:=f(x,m);
y[]:=c;y[]:=d;
y:=x*y;
y:=f(y,n);
y:=y*x;
writeln((y[]+y[]) mod p);
end;
begin
assign(input,'matrix.in');assign(output,'matrix.out');
reset(input);rewrite(output);
init;
main;
close(input);close(output);
end.

无限orz!

看来养成一个好的代码风格是必要的

NOI2013矩阵游戏的更多相关文章

  1. bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] ...

  2. BZOJ 3240: [Noi2013]矩阵游戏

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1586  Solved: 698[Submit][Status ...

  3. BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)

    3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec   Memory Limit: 256 MB Submit: 123   Solved: 73 [ Submit][ St ...

  4. (十进制高速幂+矩阵优化)BZOJ 3240 3240: [Noi2013]矩阵游戏

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3240 3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  M ...

  5. P1397 [NOI2013]矩阵游戏(递推)

    P1397 [NOI2013]矩阵游戏 一波化式子,$f[1][m]=a^{m-1}+b\sum_{i=0}^{m-2}a^i$,用快速幂+逆元求等比数列可以做到$logm$ 设$v=a^{m-1}, ...

  6. 【bzoj3240】 Noi2013—矩阵游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=3240 (题目链接) 题意$${F[1][1]=1}$$$${F[i][j]=a*F[i][j-1]+ ...

  7. BZOJ3240 [Noi2013]矩阵游戏

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  8. 3240: [Noi2013]矩阵游戏

    Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的 ...

  9. 洛谷P1397 [NOI2013]矩阵游戏

    矩阵快速幂+费马小定理 矩阵也是可以跑费马小定理的,但是要注意这个: (图是盗来的QAQ) 就是说如果矩阵a[i][i]都是相等的,那么就是mod p 而不是mod p-1了 #include< ...

随机推荐

  1. delphi xe memory leak produced in WSDLLookup.pas

    constructor TWSDLLookup.Create; begin FLookup := TDictionary<string, Variant>.Create; end; des ...

  2. envi中多波段图层叠加layer stacking

    Basic Tools——layer stacking 选择投影和输出的文件 波段1-7波段图层都叠加在一个文件中了

  3. Java学习之路:2、Mysql 链接与查询

    1.事实上我发现有了php的功力在里面,学习java起来还是不是很费劲,只是java就没有面向过程这一说 package second; import java.sql.*;//导入 public c ...

  4. Hibernate从入门到精通(六)一对一双向关联映射

    在上次的博文Hibernate从入门到精通(五)一对一单向关联映射中我们讲解了一下一对一单向关联映射,这次我们继续讲解一下与之对应的一对一双向关联映射. 一对一双向关联 与一对一单向关联映射所不同的的 ...

  5. Android中9patch图片格式(xx.9.png)介绍与制作详解

    一:9patch图片介绍: android的.9.png是android系统中一种特殊的图片格式,专门用来用来处理图片大小变化后(如拉伸)的失真,不正常,如我们看到的qq聊天中的文字气泡,不管你输入的 ...

  6. [SQL SERVER系列]存储过程,游标和触发器实例[原创]

    自己写的存储过程与游标结合使用的实例,与大家分享,也供自己查阅,仅供参考: --使用游标循环处理,删除重复的记录 declare @UserID int ) ) declare @UnitFlag i ...

  7. SQL的表连接

    每天给自己扫盲,让自己变得越博学. 继续学习<程序员的SQL金典>,这回我们来看看表连接相关的内容.表连接的相关知识在实际的项目开发当中,使用非常广. 所谓表连接,就是通过关联多张表,从而 ...

  8. 【线段树/数学/扩展欧几里得】 Bzoj 3913:奇数国

    Description 在一片美丽的大陆上有100000个国家,记为1到100000.这里经济发达,有数不尽的账房,并且每个国家有一个银行.某大公司的领袖在这100000个银行开户时都存了3大洋,他惜 ...

  9. DEDECMS采集规则,过滤,替换文章内的部分内容

    1.采集去除链接[Copy to clipboard]CODE:{dede:trim}]*)>([^<]*){/dede:trim}---------------------------- ...

  10. uva 701

    参考了一下http://hi.baidu.com/renxl51/item/e80b688f9f54aadd5e0ec1de 给一个数字x,求最小的正整数e,使得pow(2,e) == x*pow(1 ...