矩阵快速幂

矩阵快速幂

前置知识

  • 线性代数
  • 矩阵乘法(
  • 基础快速幂

原理

首先是矩阵乘法
在这里插入图片描述
A×B中 a的列必须等于b的行,A×B的每一行就是A中对应的行*B中对应的列。
然后我们就可以写一个结构体来重载乘法以及其他运算符。

//别问我为什么我zz地用了class,问就是我chun
class mat{
public:
	int n,m;
	ll v[maxn][maxn];
	mat(int n,int m):n(n),m(m){}
	void init()//初始化
	{	
		memset(v,0,sizeof(v));
	}
	void init1()
	{
		for(int i=0;i<maxn;i++)
    		for(int j=0;j<maxn;j++)
				v[i][j]=(i==j); //单位矩阵
	}
	mat operator* (const mat B) const//矩阵乘法 A(n,k)*B(k,m)=C(n,m);
	{
		mat C(n,B.m);
		C.init();
		for(int i=0;i<=n;i++)
		for(int j=0;j<=B.m;j++)
		for(int k=0;k<=m;k++)
			C.v[i][j]=(C.v[i][j]+v[i][k]*B.v[k][j]%Mod)%Mod;//Mod
		return C;
	}
	mat operator ^ (ll t)//矩阵快速幂 n=m时可用 
	{
		mat ans(n,n),now(n,n);
		ans.init1();
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				now.v[i][j]=v[i][j];
		while(t)
		{
			if(t&1) ans=ans*now;
			now=now*now;
			t>>=1;
		}
		return ans;
	}
}

其他性质:
在这里插入图片描述
既然可以进行矩阵的乘法了,那么矩阵快速幂就是把原来的整型改为矩阵类型。
但要注意的是能进行矩阵快速幂的矩阵 行数等于列数

	mat operator ^ (ll t)//矩阵快速幂 n=m时可用 
	{
		mat ans(n,n),now(n,n);
		ans.init1();
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				now.v[i][j]=v[i][j];
		while(t)
		{
			if(t&1) ans=ans*now;
			now=now*now;
			t>>=1;
		}
		return ans;
	}

解决了这个问题就可以直接套了!

用处

那么问题来了
这个玩意儿有什么用

貌似可以推一些有递推规律的递推式

样例1

比如最基础的斐波那契数列
在这里插入图片描述
首先构造初始矩阵,把递推式要用到的所有元素都加进去
在这里插入图片描述
然后构造转移矩阵,因为递推式的下一级的过程为
在这里插入图片描述

所以易得转移矩阵 a,来使a * xi=x(i+1)
转移矩阵fr为

ps:转移矩阵真的可以用填空法做,就是有的麻烦

那么求第n个项的时候就可以变为
在这里插入图片描述

样例2

在这里插入图片描述
这里有两个需要递推的元素,n和f,f后一位需要 f、n , n后一位n+1需要n、1
所以可以得到初始矩阵在这里插入图片描述
以及第n个矩阵在这里插入图片描述
所以就可以开始填空了:
第一行 3 1 0
第二行 0 1 1
第三行 0 0 1
然后代码实现填进去就可以了
设转移矩阵为 ex ,初始矩阵为 fr
得到第n个矩阵以及fn

	ex=ex^n;
	n=ex*n;
	ll fn=n.v[0];

那么就开始刷题吧 !!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值