递推求值
时间限制:
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
分析:由于n的值比较大,所以常规方法肯定会超时。根据递推式求第n个表达式的值时,通常用矩阵乘法来做。
本题要构造两个矩阵,A f2 0 0 B b a c
f1 0 0 1 0 1
1 0 0 0 0 1
因为f2和f1是已知的,当n>=3时,每次都乘以矩阵B,就能推出下一个矩阵。而矩阵的第一行第一列的元素就是所求的结果。
因为有负数的存在,这是需要加上MOD再取余。
#include<cstdio> #include<cstring> #include<algorithm> #define MOD 1000007 #define LL long long using namespace std; struct matric { LL map[3][3]; //int会爆 }; LL f1,f2,a,b,c,n; matric unit = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; matric quick2(matric q,matric p) { matric C; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { C.map[i][j]=0; for(int k=0;k<3;k++) { C.map[i][j]+=q.map[i][k]*p.map[k][j]; C.map[i][j]%=MOD; } } } return C; } matric quick1() { matric A,B; LL k=n-2; memset(A.map,0,sizeof(A.map)); memset(B.map,0,sizeof(B.map)); A.map[0][0]=b; A.map[0][1]=a; A.map[0][2]=c; A.map[1][0]=A.map[2][2]=1; B.map[0][0]=f2; B.map[1][0]=f1; B.map[2][0]=1; matric p=unit; while(k) { if(k%2==1) p=quick2(p,A); A=quick2(A,A); k=k/2; } p=quick2(p,B); return p; } int main() { int t; scanf("%d",&t); while(t--) { matric C; 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 { C=quick1(); printf("%lld\n",(C.map[0][0]+MOD)%MOD); } } return 0; }