矩阵专题 矩阵加速 矩阵快速幂

矩阵专题

#介绍

矩阵有一个神奇的作用,它可以用来快速求递推式的第 n n n项,学会这个技

能,你需要掌握这两个前置芝士 矩阵快速幂,
矩阵加速(数列)

具体怎么优化呢? 这个博客已经总结的较为全面,在这里我就不再加赘述。

代码

贴一发我写的模板

矩阵快速幂

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdio>
#define int long long
#define mod 1000000007
using namespace std;
const int maxn=1e2+10;
int n,k;
inline int read(){
	int ret=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-f;
		ch=getchar();
	}
	while(ch<='9'&ch>='0'){
		ret=ret*10+(ch^'0');
		ch=getchar();
	}
	return f*ret;
}
struct mat{
	int a[maxn][maxn];
	mat(){
		memset(a,0,sizeof(a));
	}
	inline void build(){
		for(int i=1;i<=n;i++){
			a[i][i]=1;
		}
	}
	mat operator *(const mat &b){
		mat ans;
		for(int k=1;k<=n;++k)
			for(int i=1;i<=n;++i)
				for(int j=1;j<=n;++j)
					ans.a[i][j]=(((ans.a[i][j]%mod+a[i][k]*b.a[k][j]%mod)+mod)%mod);
		return ans;
	} 
	void init(){
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			a[i][j]=read();
		}
	}
	void out(){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				cout<<a[i][j]<<" ";
			}
			cout<<endl;
		}
	}
};
mat pow(mat x,int y){
	mat ans;
	ans.build();
	while(y){
		if(y&1){
			ans=ans*x;
		}
		x=x*x;
		y=y>>1;
	}
	return ans;
}
signed main(){
//	freopen("a.txt","r",stdin);
	n=read();
	k=read();
	mat a1;	 
	a1.init();
	a1=pow(a1,k);
	a1.out();
	return 0;
}

矩阵加速

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define int long long
#define mod 1000000007
using namespace std;
const int maxn=1e2+10;
inline int read(){
	int ret=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')
			f=-f;
		ch=getchar();
	}
	while(ch<='9'&ch>='0'){
		ret=ret*10+(ch^'0');
		ch=getchar();
	}
	return f*ret;
}
struct mat{
	int a[4][4];
	mat(){
		memset(a,0,sizeof(a));
	}
	void build(){
		for(int i=1;i<=3;i++){
			a[i][i]=1;
		}
	}
	mat operator *(const mat &b1){
		mat ab;
		for(int k=1;k<=3;++k)
			for(int i=1;i<=3;++i)
				for(int j=1;j<=3;++j)
					ab.a[i][j]=(((ab.a[i][j]%mod+a[i][k]*b1.a[k][j]%mod)+mod)%mod);
		return ab;
	} 
		void out(){
		for(int i=1;i<=3;i++){
			for(int j=1;j<=3;j++){
				cout<<a[i][j]<<" ";
			}
			cout<<endl;
		}
	}
}; 
int q[maxn];
int b[maxn];
int n;
int an[maxn];
bool cmp(int x,int y){
	return q[x]<q[y];
}
mat pow(mat x,int y){
	mat ans;
	ans.build();
	while(y){
		if(y&1){
			ans=ans*x;
		}
		x=x*x;
		y=y>>1;
	}
	return ans;
}
mat mul(mat x,mat y){
	mat ans;
	for(int k=1;k<=3;k++){
		for(int i=1;i<=1;i++){
			for(int j=1;j<=3;j++){
				ans.a[i][j]=(ans.a[i][j]%mod+x.a[i][k]*y.a[k][j]%mod+mod)%mod;
			}
		}
	}
	return ans;
}
signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		q[i]=read();
		b[i]=i;
	}
	sort(b+1,b+1+n,cmp);
	mat st;
	st.a[1][1]=1;
	st.a[1][2]=1;
	st.a[2][3]=1;
	st.a[3][1]=1;
	mat ans;
	ans.a[1][1]=1;
	ans.a[1][2]=1;
	ans.a[1][3]=1; 
	int fla=0;
	for(int i=1;i<=n;i++){
		if(q[b[i]]<=3){
			an[b[i]]=1;
			continue;
		}
		if(fla==0){
			ans=mul(ans,pow(st,q[b[i]]-3));
			an[b[i]]=ans.a[1][1];
			fla=1;
			continue;
		} 
		ans=mul(ans,pow(st,q[b[i]]-q[b[i-1]]));
		an[b[i]]=ans.a[1][1];	
	} 
	for(int i=1;i<=n;i++){
		cout<<an[i]<<endl;
	} 
	return 0;
} 

最后推荐一道练习题 P1306 斐波那契公约数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值