【HDU4990】递推式

题目大意:给定序列 1, 2, 5, 10, 21, 42, 85, 170, 341 …… 求第n项 模 m的结果

递推式 f[i]  = f[i - 2] + 2 ^ (i - 1);

方法一: 构造矩阵, 求递推式

方法二: 直接推公式,递推式求和,得到 f[n] = [2 ^ (n + 1) - 1] / 3 奇数, f[n] = [2 ^ (n + 1) - 2] / 3 偶数; 其实还可以进一步化简, 注意到 2 ^ 2k % 3 = 1, 2 ^ (2k + 1) % 3 = 2,于是 f[n] = 2 ^ (n + 1) / 3 ;于是答案就是 2 ^ (n + 1) % 3m / 3 (巧妙)

源码(矩阵):

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #define mem0(a) memset(a, 0, sizeof(a))
 7 #define LL __int64
 8 using namespace std;
 9 struct Node{
10     LL a[2][2];
11 };
12 Node multi(Node a, Node b, int m)
13 {
14     Node ans;
15     mem0(ans.a);
16     for(int i = 0; i < 2; i++) {
17         for(int j = 0; j < 2; j++) {
18             for(int k = 0; k < 2; k++) {
19                 ans.a[i][j] += (a.a[i][k] * b.a[k][j]) % m;
20             }
21         }
22     }
23     return ans;
24 }
25 Node calc(Node a, int b, int m)
26 {
27     if(b == 1) return a;
28     Node tmp = calc(a, b >> 1, m);
29     int t = b & 1;
30     tmp = multi(tmp, tmp, m);
31     if(t) tmp = multi(tmp, a, m);
32     return tmp;
33 }
34 Node a0;
35 int main()
36 {
37     //freopen("in.txt", "r", stdin);
38     int n, m;
39     a0.a[0][0] = a0.a[1][0] = 1;
40     a0.a[0][1] = 0;
41     a0.a[1][1] = 4;
42     while(~scanf("%d%d", &n, &m)) {
43         LL ans = 0;
44         if(n == 1) {
45             cout<< 1 % m<< endl;
46             continue;
47         }
48         if(n == 2) {
49             cout<< 2 % m<< endl;
50             continue;
51         }
52         if(n & 1) {
53             Node one = calc(a0, (n - 1) >> 1, m);
54             ans = (one.a[0][0] + one.a[1][0] * 4) % m;
55         }
56         else {
57             Node one = calc(a0, (n - 2) >> 1, m);
58             ans = (one.a[0][0] * 2 + one.a[1][0] * 8) % m;
59         }
60         cout<< ans<< endl;
61     }
62     return 0;
63 }
View Code

 

posted @ 2014-09-08 17:55  jklongint  阅读(266)  评论(0编辑  收藏  举报