描述
给你一个递推公式:
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
来源
经典题目
思路:(详见白书201页)
之所以能够用快速幂计算矩阵,因为乘以矩阵后和乘以矩阵前变化的只有F的下标,常数部分不发生改变。
递推式:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
typedef long long LL;
const LL mod = 1000007;
using namespace std;
LL t, f1, f2, a, b, c, n;
struct mat {
LL mapp[3][3];
}base;
mat mat_mul(mat A, mat B) {
mat C;
memset(C.mapp, 0, sizeof(C.mapp));
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 3; k++) {
C.mapp[i][k] = (C.mapp[i][k] + A.mapp[i][j] * B.mapp[j][k] + mod) % mod;
}
}
}
return C;
}
mat mat_pow(mat A, LL b) {
mat ans;
memset(ans.mapp, 0, sizeof(ans.mapp));
for(int i = 0; i < 3; i++) {
ans.mapp[i][i] = 1;
}
while(b) {
if(b & 1) ans = mat_mul(ans, A);
A = mat_mul(A, A);
b >>= 1;
}
return ans;
}
int main() {
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);
continue;
}
if(n == 2) {
printf("%lld\n", (f2 + mod) % mod);
continue;
}
base.mapp[0][0] = b;
base.mapp[0][1] = a;
base.mapp[0][2] = c;
base.mapp[1][0] = 1;
base.mapp[1][1] = 0;
base.mapp[1][2] = 0;
base.mapp[2][0] = 0;
base.mapp[2][1] = 0;
base.mapp[2][2] = 1;
mat A = mat_pow(base, n - 2);
mat B, C;
memset(B.mapp, 0, sizeof(B.mapp));
B.mapp[0][0] = f2;
B.mapp[1][0] = f1;
B.mapp[2][0] = 1;
memset(C.mapp, 0, sizeof(C.mapp));
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 3; k++) {
C.mapp[i][k] = (C.mapp[i][k] + A.mapp[i][j] * B.mapp[j][k] + mod) % mod;
}
}
}
printf("%lld\n", (C.mapp[0][0] + mod) % mod);
}
return 0;
}