递推求值
时间限制:
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
f1 0 0
1 0 0
另一个为矩阵B
b a c
1 0 0
0 0 1
因为F(2)和F(1)是已知的,当n>=3时,每次都乘以矩阵B,就能推出下一个矩阵。而矩阵的第一行第一列的元素就是所求的结果。
所以利用矩阵快速幂能够快速准确地求出结果。
#include<stdio.h> #include<string.h> #define mod 1000007 #define N 3 typedef long long LL; struct Matrix { LL mat[N][N]; }; 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] += a.mat[i][k] * b.mat[k][j]; res.mat[i][j] %= mod; } } return res; } Matrix pow_matrix(Matrix a, LL n) //矩阵快速幂 { Matrix res = unit_matrix; 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; Matrix tmp, arr; scanf("%lld",&T); while(T--) { scanf("%lld%lld%lld%lld%lld%lld",&f1, &f2, &a, &b, &c, &n); if(n == 0) printf("%lld\n",(f2-f1*b-c + mod)%mod); if(n == 1) printf("%lld\n",(f1+mod)%mod); else if(n == 2) printf("%lld\n",(f2+mod)%mod); else { memset(arr.mat, 0, sizeof(arr.mat)); arr.mat[0][0] = f2; arr.mat[1][0] = f1; arr.mat[2][0] = 1; tmp.mat[0][0] = b; tmp.mat[0][1] = a; tmp.mat[0][2] = c; tmp.mat[1][0] = tmp.mat[2][2] = 1; tmp.mat[1][1] = tmp.mat[1][2] = tmp.mat[2][0] = tmp.mat[2][1] = 0; Matrix p = pow_matrix(tmp, n-2); p = mul(p, arr); LL ans = (p.mat[0][0] + mod) % mod; printf("%lld\n",ans); } } return 0; }
-
第一行是一个整数T,表示测试数据的组数(T<=10000)