矩阵快速幂
链接: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;elsereturn (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; //初始化答案矩阵aa.each[1][0]=0,a.each[1][1]=0; //和用于快速幂的矩bb.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;}
}
这就是矩阵快速幂,在快速幂的基础上用一个矩阵来构造
最主要的就是构造用于快速幂的矩阵,
当然,我这里举的例子比较简单构造。