您的位置:首页 > 其它

poj 3070 矩阵乘法

2011-06-05 22:33 218 查看
省选前几天就看到过矩阵快速幂的题,结果没引起注意,也就没去做。可是,省选第一天第一题竟然就是矩阵乘法(就是雅礼下至3岁幼童都会的那一道)。

今天去看了xqz的博文,虽然xqz不能进入省队令人惋惜,雅礼所作所为也令人不齿,但是,从博文中可以看出,xqz在考试时信念还是有所动摇,oi有我们的梦,有我们的伙伴,有我们的坚守,不论在什么情况下我们永不言败,希望xqz尽快恢复过来,在我们面前的,是整个世界,oi伴我们起航,世界的波澜将由我们掀起。

回过头来讲这道题,快速求斐波拉切数列第n项取模,由[fn-2,fn-1]-->[fn-1,fn]可得出矩阵只需左乘[0,1][1,1],由于矩阵乘法满足结合律,因此可以快速幂,说起来复杂,其实就是将一般快速幂乘的过程换成矩阵乘的函数,至于初始值就是[0,1][1,1]-->[0,1][1,1]时左乘某矩阵,自己推一下,可参见ori数组。

矩阵乘法自身便具有高效性,关键是如何构造。

话说xqz好像进了

type arr=array[1..2,1..2]of longint;
const std:arr=((0,1),(1,1));
      ori:arr=((1,0),(0,1));
      mo=10000;
var n,ans:int64;
    a,a1:arr;
function mul(a1,a2:arr):arr;
var i,j,k:longint;
begin
 fillchar(mul,sizeof(mul),0);
 for i:=1 to 2 do
  for j:=1 to 2 do
   for k:=1 to 2 do begin
    mul[i,j]:=mul[i,j]+a1[i,k]*a2[k,j];
    if mul[i,j]>mo then mul[i,j]:=mul[i,j] mod mo
   end
end;
procedure fgm(e:int64);
begin
 a:=ori;
 while e<>0 do begin
  if e and 1=1 then a:=mul(a,a1);
  a1:=mul(a1,a1);
  e:=e>>1
 end
end;
procedure init;
begin
 readln(n);
 if n=-1 then exit;
 if n<2 then begin writeln(n);exit end
        else if n=2 then begin writeln(1);exit end;
 a1:=std;
 fgm(n-2);
 ans:=(a[1,2]+a[2,2]) mod mo;
 writeln(ans)
end;
begin
assign(input,'3070.in');reset(input);
 while not(seekeof) do init;
close(input)
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: