首页 > 代码库 > 递推求值【快速幂矩阵】

递推求值【快速幂矩阵】

递推求值

 
描述

给你一个递推公式:

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 }

递推求值【快速幂矩阵】