2020-09-23

矩阵快速幂的用法
要讲矩阵快速幂,就要先了解快速幂是个啥玩意。比如说我们要求2的127次方,容易想到的做法是乘127次,也就是O(n)的时间复杂度,那么有没有效率更高的算法呢?答案是有的,那就是快速幂。

首先将127写成二进制串(1111111),所以就可以把2^127写成

 2^64 × 2^32 × 2^16 × 2^8 × 2^4 × 2^2 × 2^1

可以看到这个式子从右到左,左边的因子是右边的因子的平方,这不就很方便我们列举这些因子了吗,下一个就是上一个的平方,剩下的工作就是选择那些我们需要的因子,这里举的是一个特殊的例子(2的127次方包含了所有因子)。

如果我们要求的是2的100次方,100可以写成1100100。首先初始化 ans = 1 ,因子x = 2,
检验最后一位为0,ans 不变(不存在因子2^1),x = x^2 = 2^2(下一个因子是上一个的平方),
检验倒数第二位为0,ans不变,x = x^2 = 2^4,
检验倒数第三位为1,ans = ans * 2^4 (存在因子2^4),x = x^2 = 2^8,

检验第三位为0,ans不变,x = x^2 = 2^32,
检验第二位为1,ans = ans * 2^32 ,x = x^2 = 2^64,
检验第一位为1,ans = ans * 2^64,x = x^2 = 2^128。

代码如下

int fast_pow(int x,int n)
{
	int ans=1;
	while(n!=0)
	{
		if(n & 1)
			ans=ans*x;
		x=x*x;
		n=n>>1;
	}
	return ans;
}

了解了快速幂后,矩阵的快速幂就很容易了,就是把 x 换成矩阵就好了

int N = 10typedef long long LL;
struct mat_{
	LL m[N][N];
}; 
typedef mat_ mat;
mat mat_mul(mat A, mat B)
{
	mat C;
	memset(C.m, 0, sizeof(C.m));
	
	for(int i=0; i<N; i++)
		for(int j=0; j<N; j++)
			for(int k=0; k<N; k++)
				C.m[i][j]=(C.m[i][j] + (A.m[i][k] * B.m[k][j]) % MOD) % MOD;
	
	return C;
}
mat mat_pow(mat A, int n)
{
	mat ans;
	for(int i=0; i<N; i++)
		for(int j=0; j<N; j++)
			if(i==j) ans.m[i][j]=1;
			else ans.m[i][j]=0;
	
	while(n != 0)
	{
		if(n & 1)
			ans=mat_mul(ans, A);
		A=mat_mul(A, A);
		n >>= 1;
	}
	return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值