uva 10870

https://vjudge.net/problem/UVA-10870

题意:

f(n) = a1f(n − 1) + a2f(n − 2) + a3f(n − 3) + . . . + adf(n − d), for n > d

给出f(1),f(2) ... f(d) 以及a1,a2...ad,然后给出一个n和m的值,计算f(n) % m的值

思路:

矩阵快速幂模板题,只是构建矩阵比较困难,其实这题的构建矩阵是比较简单的,这题的模型也是一个相当广泛的模型。

   |a1 a2 a3 a4 a5|                | f[n]     |      | f[n+1] |  
   |1                      |                | f[n-1]  |      | f[n]    |  
   |     1                 |       *        | f[n-2]  | =   | f[n-1] | (空白处为0)
   |          1            |                | f[n-3]  |      | f[n-2] |
   |              1        |                | f[n-4]  |      | f[n-3] |

就是这样一个关系,可以用手推一下。

f(n) = A^(n-d) * f(d);

之后就直接套模板啦。

最后的f(n)其实是通过得到的结果矩阵的第一行乘以f(d)这个矩阵得到的,只不过乘的时候要关注原矩阵的顺序,别乘反了。

注意在n <= d的时候是直接取余输出的。(矩阵乘法的时候也要一边乘,一边取余)。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 long long d,n,m;
 5 
 6 long long f[20];
 7 
 8 struct matrix
 9 {
10     long long a[20][20];
11 };
12 
13 matrix mul(matrix x,matrix y)
14 {
15     matrix c;
16 
17     for (int i = 0;i < d;i++)
18         for (int j = 0;j < d;j++)
19     {
20         c.a[i][j] = 0;
21 
22         for (int k = 0;k < d;k++)
23         {
24             c.a[i][j] = (c.a[i][j] + x.a[i][k] * y.a[k][j] % m) % m;
25         }
26     }
27 
28     return c;
29 }
30 
31 void solve(matrix t,long long o)
32 {
33     matrix e;
34 
35     memset(e.a,0,sizeof(e.a));
36 
37     for (int i = 0;i < d;i++)
38         e.a[i][i] = 1;
39 
40     while (o)
41     {
42         if (o & 1)
43         {
44             e = mul(e,t);
45         }
46 
47         o >>= 1;
48 
49         t = mul(t,t);
50     }
51 
52     long long res = 0;
53 
54     for (int i = 0;i < d;i++)
55         res = (res + e.a[0][i] * f[d-i-1]) % m;
56 
57     printf("%lld\n",res);
58 }
59 
60 int main()
61 {
62 
63 
64     while (scanf("%lld%lld%lld",&d,&n,&m) != EOF)
65     {
66         if (d == 0 && n == 0 && m == 0) break;
67 
68         matrix p;
69 
70         memset(p.a,0,sizeof(p.a));
71 
72         for (int i = 0;i < d;i++)
73             scanf("%lld",&p.a[0][i]);
74 
75         for (int i =  1;i < d;i++)
76             p.a[i][i-1] = 1;
77 
78         for (int i = 0;i < d;i++)
79             scanf("%lld",&f[i]);
80 
81         if (n <= d)
82         {
83             printf("%lld\n",f[n-1] % m);
84 
85             continue;
86         }
87 
88         solve(p,n-d);
89     }
90 
91     return 0;
92 }

 

posted @ 2017-08-04 21:16  qrfkickit  阅读(176)  评论(0编辑  收藏  举报