关于矩阵快速幂构造矩阵的学习,推荐一篇非常完美的博客:http://blog.csdn.net/u012061345/article/details/52224623(居家旅行必备!!!!超强)
题目链接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=5950
题目大意:
给你一个递推公式,然后让你求解第n项的结果。
题目思路:
给你递推式,那么这就是一个很裸的矩阵快速幂的题目。那么解题的关键就是求解相应的系数矩阵了。
已知递推公式:F(n) = 2*F(n-2) + F(n-1) + n4 和F(1) = a,F(2) = b;给定一个N,求F(N)等于多少?
不知道的点:
一开始用的以前写的模板,狂wa不止,改了板子才写对了。不知所以。
狂wa的代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 2147493647; //这个地方是 ll 而不是 int
const int Size = 7; //size的大小按照题目的最大数据大小给
struct Matrix
{
ll m[Size][Size];
};
Matrix Mul(Matrix a,Matrix b) //矩阵的乘法
{
Matrix c;
memset(c.m,0,sizeof(c.m));
for(int i=0;i<Size;i++)
for(int j=0;j<Size;j++)
for(int k=0;k<Size;k++)
c.m[i][j] = ((a.m[i][k]*b.m[k][j])%mod+c.m[i][j])%mod;
return c;
}
Matrix quick(Matrix a,ll n) //二分的快速幂处理
{
Matrix res;
memset(res.m,0,sizeof(res.m));
for(int i=0;i<Size;i++)
res.m[i][i]=1;
while(n){
if(n&1) res = Mul(res,a);
n>>=1;
a = Mul(a,a);
}
return res;
}
int main()
{
Matrix p;
memset(p.m,0,sizeof(p.m));
p.m[0][1] = 1;
p.m[1][1] = p.m[1][2] = p.m[1][6] = 1;
p.m[2][2] = p.m[2][6] = 1;
p.m[1][0] = 2; p.m[1][3] = p.m[1][5] = p.m[2][3] = p.m[2][5] = 4;
p.m[1][4] = p.m[2][4] = 6;
p.m[3][3] = p.m[4][4] = p.m[5][5] = p.m[6][6] = 1;
p.m[3][6] = p.m[4][6] = p.m[5][6] = 1;
p.m[3][4] = p.m[3][5] = 3;
p.m[4][5] = 2;
int t;
ll n,a,b;
scanf("%d",&t);
while(t--){
scanf("%I64d %I64d %I64d",&n,&a,&b);
if(n==1) printf("%I64d\n",a);
else if(n==2) printf("%I64d\n",b);
else{
Matrix ans = quick(p,n-2);
ll ANS = 0;
ANS = (ANS+ans.m[1][0]*a)%mod;
ANS = (ANS+ans.m[1][1]*b)%mod;
ANS = (ANS+ans.m[1][2]*16)%mod;
ANS = (ANS+ans.m[1][3]*8)%mod;
ANS = (ANS+ans.m[1][4]*4)%mod;
ANS = (ANS+ans.m[1][5]*2)%mod;
ANS = (ANS+ans.m[1][6]*1)%mod;
printf("%I64\n",ANS);
}
}
return 0;
}
ac代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 2147493647;
const int size = 7;
//定义矩阵乘法
struct matrix{
ll arr[size][size];
matrix operator*(matrix b){ //乘法重载
matrix ans;
ll tmp;
for(int i=0; i<size; i++)
for(int j=0; j<size; j++){
ans.arr[i][j] = 0;
for(int k=0; k<size; k++){
tmp = (arr[i][k]*b.arr[k][j])%mod;
ans.arr[i][j] = (ans.arr[i][j] + tmp)%mod;
}
}
return ans;
}
};
//矩阵快速幂
matrix quick_pow(matrix a,ll N){
matrix ans;
memset(ans.arr,0,sizeof(ans.arr));
for(int i=0; i<size; i++)
ans.arr[i][i] = 1;
while(N){
if(N&1)
ans = ans*a;
a = a*a;
N /= 2;;
}
return ans;
}
int main(){
matrix a;
memset(a.arr,0,sizeof(a.arr));
a.arr[0][1] = 1;
a.arr[1][1] = a.arr[1][2] = a.arr[1][6] = 1;
a.arr[2][2] = a.arr[2][6] = 1;
a.arr[1][0] = 2; a.arr[1][3] = a.arr[1][5] = a.arr[2][3] = a.arr[2][5] = 4;
a.arr[1][4] = a.arr[2][4] = 6;
a.arr[3][3] = a.arr[4][4] = a.arr[5][5] = a.arr[6][6] = 1;
a.arr[3][6] = a.arr[4][6] = a.arr[5][6] = 1;
a.arr[3][4] = a.arr[3][5] = 3;
a.arr[4][5] = 2;
int T;
scanf("%d",&T);
ll N,aa,bb;
while(T--){
scanf("%I64d %I64d %I64d",&N,&aa,&bb);
if(N==1)
printf("%I64d\n",aa);
else if(N==2)
printf("%I64d\n",bb);
else{
matrix ans = quick_pow(a,N-2);
ll ANS = 0;
ANS = (ANS+ans.arr[1][0]*aa)%mod;
ANS = (ANS+ans.arr[1][1]*bb)%mod;
ANS = (ANS+ans.arr[1][2]*16)%mod;
ANS = (ANS+ans.arr[1][3]*8)%mod;
ANS = (ANS+ans.arr[1][4]*4)%mod;
ANS = (ANS+ans.arr[1][5]*2)%mod;
ANS = (ANS+ans.arr[1][6]*1)%mod;
printf("%I64d\n",ANS);
}
}
return 0;
}