首页 > 代码库 > 【HDU4990】递推式

【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

 

【HDU4990】递推式