洛谷 P4451 [国家集训队]整数的lqp拆分

题意简述

\(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)\)\(g(0) = 0, g(1) = 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]);
}

猜你喜欢

转载自www.cnblogs.com/xuyixuan/p/9898042.html