您的位置:首页 > 其它

nyoj301 递推求值(矩阵快速幂)

2016-02-12 17:14 381 查看
题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=301

题目大意:

计算递推式f(x)=a*f(x-2)+b*f(x-1)+c,求f(n)。

范围:

0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)

思路:

由于n很大,所以不能够直接采用递推的方法。

由于是一个方程式,所以可以转化为矩阵乘法,又是一个递推式,就想到用矩阵快速幂解决。

矩阵快速幂:

就是矩阵的快速乘法,跟数的求快速幂是一样的。

--------------------------------------------------------------------------------------------------------------

所以这个递推式可以转化为矩阵A

b a c

1 0 0

0 0 1

和矩阵B

f2

f1

1

的乘积A*B.

得到的就是答案f(3)。

然后我们就可以通过递推的方式计算出f(n)。可以知道f(n)=A^(n-2)*B,利用矩阵快速幂算出A^(n-2),就解决问题了。

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#define n 100
#define ll long long
#define mod 1000007
using namespace std;
struct Mat{
ll mat[5][5];
};
int ss;
Mat operator * (Mat a, Mat b) {
Mat c;
memset(c.mat, 0, sizeof(c.mat));
int i, j, k;
for(k = 0; k < 4; ++k) {
for(i = 0; i < 4; ++i) {
for(j = 0; j < 4; ++j) {
c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]);
c.mat[i][j]=(c.mat[i][j]+mod)%mod;
}
}
}
return c;
}
Mat operator ^ (Mat a, ll k) {
Mat c;
int i, j;
for(i = 0; i < 4; ++i)
for(j = 0; j < 4; ++j)
c.mat[i][j] = (i == j);    //初始化为单位矩阵

for(; k; k >>= 1) {
if(k&1) c = c*a;

a = a*a;
}
return c;
}
int main()
{
Mat x,y;
int i,j,k,N,T,f1,f2,a,b,c;
scanf("%lld",&T);
while(T--)
{
scanf("%d%d%d%d%d%d",&f1,&f2,&a,&b,&c,&N);
memset(x.mat,0,sizeof(x.mat));
memset(y.mat,0,sizeof(y.mat));
x.mat[1][1]=b;
x.mat[1][2]=a;
x.mat[1][3]=c;
x.mat[2][1]=1;
x.mat[2][2]=0;
x.mat[2][3]=0;
x.mat[3][3]=1;
y.mat[1][1]=f2;
y.mat[2][1]=f1;
y.mat[3][1]=1;
//    scanf("%d",&N);
if(N==1){
printf("%d\n",f1);
continue;
}
x=x^(N-2);
x=x*y;
printf("%lld\n",(x.mat[1][1]+mod)%mod);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: