矩阵快速幂的最简单用法

矩阵快速幂

链接:https://ac.nowcoder.com/acm/contest/1168/K
来源:牛客网

题目描述
这个勇者明明超强却过分慎重,勇者龙宫院圣哉与n名冒险者一起去讨伐神秘魔物,龙宫院圣哉十分谨慎,他只会在最后一刻出手,
每名冒险者轮流攻击魔物,冒险者的攻击有着某种规律,目前造成的总伤害是上一名冒险者攻击后造成的总伤害的4倍与上上名冒
险者攻击后造成的总伤害的3倍之和,即当前总伤害f(n)=4f(n-1)+3f(n-2)(魔物的奇怪设定使总伤害忽高忽低),又由于异世界的奇异设定,冒险者们的总伤害
不会超过666666,即对666666取模,龙宫院圣哉清楚的知道这个魔物的血量为m(m>666666),他想知道在所有的冒险者攻
击完了以后,自己需要造成多少点伤害才能杀死魔物?目前第一名冒险者攻击后总共造成了4点伤害,第二名冒险者攻击后总共造
成了233点伤害。
输入描述:
输入一行n,m,处理到文件结束

666666<m<1e9
2<n<1e9
输出描述:
输出一个整数
示例1
输入

3 666667
输出

665723
显然只是一道递推或者递归的题目。
递归代码如下

#include<iostream>
#define mood 666666
using namespace std;
long long what(int n)
{
	if(n==1)
		return 4;
	else if(n==2)
		return 233;
	else
		return (what(n-1)*4+what(n-2)*3)%mood; 
}
int main()
{
	long long n,sum;
	while(cin>>n>>sum) {
		cout<<sum-what(n)<<endl;
	}
}

这种方法可处理n较小的情况,但是因为n最大可取到十亿,显然会超时,所以这里就用到了矩阵快速幂

第一步构造矩阵
在这里插入图片描述这样就构造了一个用于快速幂的矩阵,但是一定要注意构造的矩阵一定要是方阵,这样才能做多次相乘变换。

#include<bits/stdc++.h>
#define N 2               //由于这里只有两步递推关系,所以这里只要用一个2*2的矩阵
typedef long long ll;
#define mood 666666
using namespace std;
struct unit               //定义一个结构体后面便于设置二阶矩阵
{
	ll each[N][N];
};
unit what(unit a,unit b)					//用于矩阵相乘
{
	unit temp;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++) {
			temp.each[i][j]=0;
			for(int k=0;k<N;k++) {
				temp.each[i][j]+=a.each[i][k]*b.each[k][j];
				temp.each[i][j]%=mood;
			}
		}
	return temp;				//返回矩阵相乘的结果
}
int main()
{
	int s,sum;
	while(cin>>s>>sum) {
		if(s==1) {
			cout<<sum-4<<endl;
			continue;
		}
		else if(s==2) {
			cout<<sum-233<<endl;
			continue;
		}
		unit a,b;
		a.each[0][0]=233,a.each[0][1]=4;		//初始化答案矩阵a
		a.each[1][0]=0,a.each[1][1]=0;			//和用于快速幂的矩b
		b.each[0][0]=4,b.each[0][1]=1;
		b.each[1][0]=3,b.each[1][1]=0;
		s-=2;
		while(s>0) {
			if(s&1)
				a=what(a,b);
			b=what(b,b);
			s >>= 1;
		}
		cout<<sum-a.each[0][0]<<endl;
	}	
}
 

这就是矩阵快速幂,在快速幂的基础上用一个矩阵来构造
最主要的就是构造用于快速幂的矩阵,
当然,我这里举的例子比较简单构造。

原文地址:https://www.cnblogs.com/lifehappy/p/12601208.html