矩陣乘法(乘,遞推,快速冪)學習筆記
阿新 • • 發佈:2019-05-06
自己 mod ... 遞推 str class clu 矩陣 快速
矩陣,是一個好東西。
大家都知道,斐波那契數列是滿足如下性質的一個數列:
• f(1) = 1
• f(2) = 1
• f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 為整數)
題目描述
請你求出 f(n) mod 1000000007 的值。
輸入輸出格式
輸入格式:
·第 1 行:一個整數 n
輸出格式:
第 1 行: f(n) mod 1000000007 的值
輸入輸出樣例
輸入樣例#1:5輸出樣例#1:
5輸入樣例#2:
10輸出樣例#2:
55
說明
對於 60% 的數據: n ≤ 92
對於 100% 的數據: n在long long(INT64)範圍內。
斐波那契,基礎遞推吧。。但是數據範圍讓線性遞推望而卻步...
這時候,我們列出一個式子:
f(n)=f(n-1)+f(n-2);
f(n)=1*f(n-1)+1*f(n-2);
我們把f(n)和f(n-1):
這時發現:
於是我們只需要計算
1 1
1 0
的n-1次方就行了。
個人對於矩陣的計算方式一直很迷...看了不少博客,都沒有明白,最後自己總結了一條規律:
第一個矩陣的x行*第二個矩陣的y列,結果相加,作為結果矩陣的(x行,y列)處的數。
矩陣的快速冪:
即使是可以省去大量空間,一次一次推還是會超時...
n-1次方嘛,很容易想到卡速米這個東西。
其實和卡速米一樣,逢二平方即可。
於是上代碼(感覺各個博客,題解的馬蜂都好毒瘤啊。。):
#include<bits/stdc++.h> using namespace std; const int mod=1000000007; long long int n; struct node { long long int a[3][3]; }; node mul(node x,node y) { node e; e.a[1][1]=e.a[1][2]=e.a[2][1]=e.a[2][2]=0;//初始化矩陣全都是0;for(int i=1;i<=2;i++) { for(int j=1;j<=2;j++) { for(int k=1;k<=2;k++) { e.a[i][j]=(e.a[i][j]+x.a[i][k]*y.a[k][j])%mod;//呱 } } } return e; } node ksm(node x,long long int y) { node ans; ans.a[1][1]=1; ans.a[1][2]=1; ans.a[2][1]=0; ans.a[2][2]=0; while(y) { if(y&1) ans=mul(ans,x); //這裏是要寫成賦值,我居然在這裏卡了好久 x=mul(x,x); y>>=1;//據說位運算能加速然而就快了1ms。。。 } return ans; } int main() { scanf("%lld",&n);//不開longlong見祖宗 node e; e.a[1][1]=e.a[1][2]=e.a[2][1]=1; e.a[2][2]=0;//初始化1110矩陣 if(n==1||n==2)//對n=1,2特判 { printf("1"); return 0; } node ans=ksm(e,n-2);//卡速米真好吃 printf("%lld",ans.a[1][1]); return 0; }
(完)
矩陣乘法(乘,遞推,快速冪)學習筆記