1. 程式人生 > >矩陣乘法&矩陣快速冪

矩陣乘法&矩陣快速冪

剛好在複習dp,順便把矩陣快速冪加速遞推給複習了。

首先矩陣乘法:f[i][j]=\sum_{k=1}^{sizeA[][K]/sizeB[K][]}A[i][k]*B[k][j]

我們觀察斐波那契數列f[n]=f[n-1]+f[n-2],我們構造矩陣乘法

A:[ fn-2 fn-1]

B:[0 1]

    [1 1]

C=A*B=[fn-1 fn-2+fn-1]=[fn-1 fn]

所以對於C[fn-1 fn],不難得出C=[f1 f2]*B^(n-2),而B是預先設定好的矩陣,於是就可以用上矩陣快速冪。

慄一、廣義斐波那契數列

Description

廣義的斐波那契數列是指形如a(n)=p*a(n-1)+q*a(n-2)的數列。今給定數列的兩係數p和q,以及數列的最前兩項a(1)和a(2),另給出兩個整數n和m,試求數列的第n項a(n)除以m的餘數。

Input

輸入包含一行6個整數。依次是p,q,a(1),a(2),n,m,其中在p,q,a(1),a(2)整數範圍內,n和m在長整數範圍內。

Output

輸出包含一行一個整數,即a(n)除以m的餘數。

Sample Input

1 1 1 1 10 7

Sample Output

6

【樣例說明】 數列第10項是55,除以7的餘數為6。

#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
#define int long long
int p,q,n,m,f1,f2;
struct Martix{
	int a[10][10];
	inline void init(bool flag){//可構造單位矩陣 
		memset(a,0,sizeof(a));
		if(flag)Inc(i,1,4)a[i][i]=1;
	}
};
inline Martix mul(Martix a,Martix b,int I,int J,int K,int Mod){
	Martix ans;
	ans.init(0);
	Inc(i,1,I)Inc(j,1,J)Inc(k,1,K)(ans.a[i][j]+=(a.a[i][k]*b.a[k][j]))%=Mod;
	return ans;
}
inline int quick_pow(int lm,int Mod){
	Martix a;
	a.a[1][1]=0;
	a.a[1][2]=q;
	a.a[2][1]=1;
	a.a[2][2]=p;//構造矩陣A 
	Martix ans;
	ans.init(1);
	while(lm){
		if(lm&1)ans=mul(ans,a,2,2,2,Mod);
		a=mul(a,a,2,2,2,Mod);
		lm>>=1;
	}
	return (ans.a[1][2]*f1+ans.a[2][2]*f2)%Mod;
}
signed main(){
	scanf("%lld%lld%lld%lld%lld%lld",&p,&q,&f1,&f2,&n,&m);
	if(n==1)cout<<f1%m<<"\n";
	else if(n==2)cout<<f2%m<<"\n";
	else cout<<quick_pow(n-2,m)<<"\n";
	return 0;
}

慄二、連分數

有時間再寫吧~