矩阵乘法&矩阵快速幂

刚好在复习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;
}

栗二、连分数

有时间再写吧~

猜你喜欢

转载自blog.csdn.net/dancingz/article/details/81092835
今日推荐