洛谷 P4451 [國家集訓隊]整數的lqp拆分
阿新 • • 發佈:2018-11-02
題意簡述
設\(F_{x}\)為斐波那契數列第\(x\)項
將一個數\(n\)拆分為\(a{1}, a{2}, ..., a{m}\), 即\(a{1} + a{2} +...+ a{m} = n\)
求\(\sum\prod\limits_{i =1}^m F_{a_i}\)
題解
遞推
設\(g(i)\)為當n = i時的答案
所以
\(g(i) = \sum\limits_{j = 1} ^ {i - 1} g(j) * F_{i - j} + F_i\)
\(g(i + 1) = \sum\limits_{j = 1} ^ {i} g(j) * F_{i + 1 - j} + F_{i + 1}\)
\(g(i + 1) - g(i)\)
$ = \sum\limits_{j = 1} ^ {i - 1} g(j) * (F_{i + 1 - j} - F_{i - j}) + g(i) * F_1 + F_{i + 1} - F_i$
$ = \sum\limits_{j = 1} ^ {i - 1} g(j) * F_{i - j - 1} + g(i) + F_{i - 1}$
$ = \sum\limits_{j = 1} ^ {i - 2} g(j) * F_{i - j - 1} + F_{i - 1} + g(i)$
$ = g(i - 1) + g(i)$
所以 \(g(i + 1) = 2 * g(i) + g(i - 1)\)
再直接遞推或矩陣快速冪求第\(n\)項即可
程式碼
#include <cstdio> typedef long long ll; const int mod = 1000000007; int T, N; int n; struct Matrix { int a[4][4]; Matrix& operator =(const Matrix& x) { for (register int i = 1; i <= N; ++i) for (register int j = 1; j <= N; ++j) a[i][j] = x.a[i][j]; return *this; } }; Matrix a, b, c; Matrix Mul(const Matrix& x, const Matrix& y) { Matrix s; for (register int i = 1; i <= N; ++i) for (register int j = 1; j <= N; ++j) s.a[i][j] = 0; for (register int k = 1; k <= N; ++k) for (register int i = 1; i <= N; ++i) for (register int j = 1; j <= N; ++j) s.a[i][j] = (s.a[i][j] + (ll)x.a[i][k] * y.a[k][j] % mod) % mod; return s; } Matrix _pow(Matrix x, int y) { Matrix s; for (register int i = 1; i <= N; ++i) for (register int j = 1; j <= N; ++j) s.a[i][j] = (i == j); for (; y; y >>= 1, x = Mul(x, x)) if (y & 1) s = Mul(s, x); return s; } int main() { N = 2; scanf("%d", &n); c.a[1][1] = 0; c.a[1][2] = 1; a.a[2][1] = a.a[1][2] = 1; a.a[2][2] = 2; if (n <= 1) {printf("%d\n", c.a[1][n + 1]); return 0; } b = Mul(c, _pow(a, n - 1)); printf("%d\n", b.a[1][2]); }