总结:满足下面这句话的条件,都可以考虑矩阵乘法+快速幂——把一个向量v变成另一个向量v',并且v'的每一个分量都是v的各个分量的线性组合。

 

1、UVa 10870, Recurrences

题意:给出递推关系f(n) = a1*f(n-1) + a2*f(n-2)....ad*f(n-d),给出d, n, m, a1, a2, ...ad, f(1), f(2)...f(n-d),求f(n) % m。

解法:矩阵乘法+快速幂。这是我第一次做矩阵乘法的题,由于是专题训练,一上来就构造成f(n) = G * F(n-1),只需要G = [a1, a2,...ad],F(n-1) = [f(n-1), f(n-2),...f(n-d)]T即可。

   但是,这样构造显然是不对的,我们要构造出的灯式形势应该是这样的(矩阵)F(n) = (d*d的矩阵)G * (矩阵)F(n-1),只有这样的形式(G为d*d),才能使用矩阵乘法快速幂。

   所以,F(n) = [f(n-d), f(n-d+1),...f(n-1)]T,

   G = [0   1        ]

          [    0    1          ]

      [...     ...    ]

      [                     0     1]                      

      [ad a(d-1)....    a2  a1] (d*d的矩阵)

   构造出来,这道题便得以解决。

tag:math, matrix

 1 /*
 2  * Author:  Plumrain
 3  * Created Time:  2013-09-10 21:16
 4  * File Name: math-UVa-10870.cpp
 5  */
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<cstring>
 9 
10 using namespace std;
11 
12 #define CLR(x) memset(x, 0, sizeof(x))
13 #define out(x) cout<<#x<<":"<<(x)<<endl
14 #define tst(a) cout<<#a<<endl
15 
16 typedef int matrix[20][20];
17 
18 const int N = 15;
19 int mod;
20 int a[N+5], f[N+5];
21 
22 void mtx_init (matrix& A, int n)
23 {
24     CLR (A);
25     for (int i = 0; i < (n-1); ++ i)
26         A[i][i+1] = 1;
27     for (int i = 0; i < n; ++ i)
28         A[n-1][i] = a[n-i];
29 }
30 
31 void mtx_mul (matrix& A, matrix B, int n)
32 {
33     matrix ret;
34     CLR (ret);
35     for (int i = 0; i < n; ++ i)
36         for (int k = 0; k < n; ++ k)
37             for (int j = 0; j < n; ++ j)
38                 ret[i][k] = (((A[i][j] * B[j][k]) % mod) + ret[i][k]) % mod;
39 
40     for (int i = 0; i < n; ++ i)
41         for (int j = 0; j < n; ++ j)
42             A[i][j] = ret[i][j];
43 }
44 void mtx_pow (matrix& A, int num, int n)
45 {
46     matrix ret;
47     CLR (ret);
48     for (int i = 0; i < n; ++ i)
49         ret[i][i] = 1; 
50     while (num > 0){
51         if (num & 1) 
52             mtx_mul (ret, A, n);
53         num >>= 1;
54         mtx_mul (A, A, n);
55     }
56 
57     for (int i = 0; i < n; ++ i)
58         for (int j = 0; j < n; ++ j)
59             A[i][j] = ret[i][j];
60 }
61 
62 int gao (int m, int n)
63 {
64     matrix A;
65     mtx_init (A, n);
66     
67     mtx_pow (A, m-n, n); 
68     int ret = 0;
69     for (int i = 0; i < n; ++ i)
70         ret = (((A[n-1][i] * f[i+1]) % mod) + ret) % mod;
71     if (ret < 0) ret += mod;
72     return ret;
73 }
74 
75 int main()
76 {
77     int n, m; 
78     while (scanf ("%d%d%d", &n, &m, &mod) != EOF && n){
79         for (int i = 1; i <= n; ++ i){
80             scanf ("%d", &a[i]);
81             a[i] %= mod;
82         }
83         for (int i = 1; i <= n; ++ i){
84             scanf ("%d", &f[i]);
85             f[i] %= mod;
86         }
87 
88         if (m <= n) printf ("%d\n", f[m]);
89         else printf ("%d\n", gao (m, n));
90     }
91     return 0;
92 }
View Code

相关文章: