您的位置:首页 > 其它

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

2017-04-12 21:51 295 查看
题目:


递推求值

时间限制:1000 ms  |  内存限制:65535 KB
难度:4

描述

给你一个递推公式:

f(x)=a*f(x-2)+b*f(x-1)+c

并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值。

注意:-1对3取模后等于2

输入第一行是一个整数T,表示测试数据的组数(T<=10000)

随后每行有六个整数,分别表示f(1),f(2),a,b,c,n的值。

其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
输出输出f(n)对1000007取模后的值
样例输入
2
1 1 1 1 0 5
1 1 -1 -10 -100 3


样例输出
5
999896
4000


来源经典题目
上传者张云聪

这是一道矩阵快速幂的入门加模板题

矩阵快速幂:

1:思想

矩阵快速幂的思想就是跟数的快速幂一样,假如我们要求2^11,次方,我们可以把 11 写成 1+2+8 ,也就是2^0 + 2^1 + 2^3 。那么把一个O(n)的时间复杂度降到了log(n)

矩阵快速幂的思想和数的快速幂是一模一样的,就是要自己实现矩阵的乘法,然后可以套数的快速幂的模板。

2:难点

矩阵题目的难点在于构造矩阵,一般用于有能够推出递推式的题目,推出递推式之后,发现递推O(n)的复杂度时间比较大,那么我们可以构造一个矩阵,然后用矩阵快速幂降低到log(n)的时间复杂度

代码:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000007
#define N 3
#define M 1000000+10
#define ll long long
using namespace std;
struct Matrix
{
ll mat

;
};
Matrix unit_matrix=
{
1,0,0,
0,1,0,
0,0,1
};//单位矩阵

Matrix mul(Matrix a,Matrix b)//矩阵相乘
{
Matrix res;
for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
{
res.mat[i][j]=0;
for(int k=0; k<N; ++k)
res.mat[i][j]=(res.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
}
return res;
}

Matrix pow_matrix(Matrix a,ll n)//矩阵快速幂
{
Matrix res=unit_matrix;
while(n)
{
if(n&1)
res=mul(res,a);
a=mul(a,a);
n>>=1;
}
return res;
}

int main()
{
ll t,f1,f2,a,b,c,n;
Matrix tmp,arr;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n);
if(n==1)
printf("%lld\n",(f1+mod)%mod);
else if(n==2)
printf("%lld\n",(f2+mod)%mod);
else
{
mem(arr.mat,0);
mem(tmp.mat,0);
arr.mat[0][0]=f2,arr.mat[0][1]=f1,arr.mat[0][2]=1;//构造初始矩阵
tmp.mat[0][0]=b,tmp.mat[1][0]=a,tmp.mat[2][0]=c;
tmp.mat[0][1]=tmp.mat[2][2]=1;
Matrix p=pow_matrix(tmp,n-2);
p=mul(arr,p);//注意p和arr不要写反了
ll ans=(p.mat[0][0]+mod)%mod;
printf("%lld\n",ans);
}
}
return 0;
}

2017/10/10重做代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<iostream>
#include<stack>
#include<queue>
#include<vector>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define mod 1000007
#define debug() puts("what the fuck!!!")
#define ll long long
using namespace std;
const ll N=3;
struct Matrix
{
ll a

;
Matrix()
{
mem(a,0);
}
void init()
{
mem(a,0);
for(ll i=0; i<N; i++)
a[i][i]=1;
}
};
void print(Matrix a)
{
for(ll i=0; i<N; i++)
{
for(ll j=0; j<N; j++)
printf("%d ",a.a[i][j]);
puts("");
}
}
Matrix mul(Matrix a,Matrix b)
{
Matrix ans;
for(ll i=0; i<N; i++)
for(ll j=0; j<N; j++)
for(ll k=0; k<N; k++)
{
ans.a[i][j]=(ans.a[i][j]%mod+a.a[i][k]*b.a[k][j]%mod)%mod;
}
return ans;
}
Matrix mat_pow(Matrix a,ll n)
{
Matrix ans;
ans.init();
while(n)
{
if(n&1)
ans=mul(ans,a);
a=mul(a,a);
n>>=1;
}
return ans;
}
int main()
{
ll f1,f2,a,b,c,n,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n);
if(n==1)
printf("%lld\n",(f1+mod)%mod);
else if(n==2)
printf("%lld\n",(f2+mod)%mod);
else
{
Matrix A;
A.a[0][0]=b,A.a[1][0]=a,A.a[2][0]=c;
A.a[0][1]=A.a[2][2]=1;
Matrix p=mat_pow(A,n-2);
Matrix B;
B.a[0][0]=f2,B.a[0][1]=f1;
B.a[0][2]=1;
Matrix ans=mul(B,p);
printf("%lld\n",(ans.a[0][0]+mod)%mod);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: