递推求值快速幂矩阵
Posted 唐唐123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递推求值快速幂矩阵相关的知识,希望对你有一定的参考价值。
递推求值
- 描述
-
给你一个递推公式:
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
//初始化矩阵arr memset(arr.mat, 0, sizeof(arr.mat)); arr.mat[0][0] = f2; arr.mat[1][0] = f1; arr.mat[2][0] = 1;
另一个为矩阵B
b a c
1 0 0
0 0 1
//初始化矩阵tmp 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;
- 相乘后的结果为
- f2*b+f1*a+1*c f2*a+0+0 f2*c+0+0
- f1*b+0+0 a*f+0+0 f1*c+0+0
- c*1+0+0 1*a+0+0 1*c+0+0
- (备注:任何矩阵与单位矩阵(n*n)相乘后,不改变原来矩阵的值)
因为F(2)和F(1)是已知的,当n>=3时,每次都乘以矩阵B,就能推出下一个矩阵。而矩阵的第一行第一列的元素就是所求的结果。
所以利用矩阵快速幂能够快速准确地求出结果。
AC代码:
1 #include<stdio.h> 2 #include<string.h> 3 #define mod 1000007 4 #define N 3 5 typedef long long LL; 6 struct Matrix 7 { 8 LL mat[N][N]; 9 }; 10 11 Matrix unit_matrix = 12 { 13 1, 0, 0, 14 0, 1, 0, 15 0, 0, 1 16 }; //单位矩阵 17 18 Matrix mul(Matrix a, Matrix b) //矩阵相乘 19 { 20 Matrix res; 21 for(int i = 0; i < N; i++) 22 for(int j = 0; j < N; j++) 23 { 24 res.mat[i][j] = 0; 25 for(int k = 0; k < N; k++) 26 { 27 res.mat[i][j] += a.mat[i][k] * b.mat[k][j]; 28 res.mat[i][j] %= mod; 29 } 30 } 31 return res; 32 } 33 34 Matrix pow_matrix(Matrix a, LL n)//矩阵快速幂 35 { 36 Matrix res = unit_matrix; 37 while(n != 0) 38 { 39 if(n & 1) 40 res = mul(res, a); 41 a = mul(a, a); 42 n >>= 1; 43 } 44 return res; 45 } 46 47 int main() 48 { 49 LL n, f1, f2, a, b, c, T; 50 Matrix tmp, arr; 51 scanf("%lld",&T); 52 while(T--) 53 { 54 scanf("%lld%lld%lld%lld%lld%lld",&f1, &f2, &a, &b, &c, &n); 55 if(n == 1) 56 printf("%lld\n",(f1+mod)%mod); 57 else if(n == 2) 58 printf("%lld\n",(f2+mod)%mod); 59 else 60 { 61 //初始化矩阵arr 62 memset(arr.mat, 0, sizeof(arr.mat)); 63 arr.mat[0][0] = f2; arr.mat[1][0] = f1; arr.mat[2][0] = 1; 64 //初始化矩阵tmp 65 tmp.mat[0][0] = b; tmp.mat[0][1] = a; tmp.mat[0][2] = c; 66 tmp.mat[1][0] = tmp.mat[2][2] = 1; 67 tmp.mat[1][1] = tmp.mat[1][2] = tmp.mat[2][0] = tmp.mat[2][1] = 0; 68 69 Matrix p = pow_matrix(tmp, n-2);//相当于求tmp^(n-2) 70 p = mul(p, arr); 71 LL ans = (p.mat[0][0] + mod) % mod; 72 printf("%lld\n",ans); 73 } 74 } 75 return 0; 76 }
以上是关于递推求值快速幂矩阵的主要内容,如果未能解决你的问题,请参考以下文章