矩阵快速幂
链接: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;
}
}
这就是矩阵快速幂,在快速幂的基础上用一个矩阵来构造
最主要的就是构造用于快速幂的矩阵,
当然,我这里举的例子比较简单构造。