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


    矩阵专题

    介绍

    矩阵有一个神奇的作用,它可以用来快速求递推式的第(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 斐波那契公约数

  • 相关阅读:
    【leetcode】三维形体投影面积
    【leetcode】区域和检索
    【leetcode】二叉搜索树的范围和
    【leetcode】数组序号转换
    【leetcode】赎金信
    【leetcode】矩形重叠
    【leetcode】转变日期格式
    053-158
    053-268
    053-160
  • 原文地址:https://www.cnblogs.com/rpup/p/13912429.html
Copyright © 2020-2023  润新知