【矩阵快速幂*模板】nyoj 301 递推求值

来源:互联网 发布:苹果手机清除淘宝缓存 编辑:程序博客网 时间:2024/04/28 19:30

递推求值

时间限制: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取模后的值
样例输入
21 1 1 1 0 51 1 -1 -10 -100 3
样例输出
5999896
来源

分析:由于n的值比较大,所以常规方法肯定会超时。根据递推式求第n个表达式的值时,通常用矩阵乘法来做。

本题要构造两个矩阵,

其中一个为矩阵A,作为初始矩阵

所以利用矩阵快速幂能够快速准确地求出结果。

f2  0   0

f1  0   0

1   0   0

另一个为矩阵B

b   a   c

1   0   0

0   0   1

因为F(2)和F(1)是已知的,当n>=3时,每次都乘以矩阵B,就能推出下一个矩阵。而矩阵的第一行第一列的元素就是所求的结果。

代码

 #include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<map>using namespace std;typedef pair<int,int > P;typedef long long LL;const int maxn=100;#define N 3#define mod 1000007struct Matrix{    LL mat[N][N];    Matrix()    {        memset(mat,0,sizeof(mat));    }};Matrix mul(Matrix a,Matrix b){    Matrix res;    for(int i=0; i<N; i++)        for(int j=0; j<N; j++)        {            for(int k=0; k<N; k++)            {                res.mat[i][j]+=a.mat[i][k]*b.mat[k][j];                res.mat[i][j]%=mod;            }        }    return res;}Matrix pow_matrix(Matrix a,LL n)//矩阵快速幂;{    Matrix res;    for(int i=0;i<N;i++)  //初始化为单位矩阵;      res.mat[i][i]=1;    while(n!=0)    {        if(n&1)            res=mul(res,a);        a=mul(a,a);        n>>=1;    }    return res;}int main(){    LL n,f1,f2,a,b,c,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,B;            A.mat[0][0]=f2;  //构造矩阵!!            A.mat[1][0]=f1;            A.mat[2][0]=1;            B.mat[0][0]=b;            B.mat[0][1]=a;            B.mat[0][2]=c;            B.mat[1][0]=1;            B.mat[2][2]=1;            B=pow_matrix(B,n-2);            A=mul(B,A);            printf("%lld\n",(A.mat[0][0]+mod)%mod);        }    }    return 0;}

0 0
原创粉丝点击