LOJの#10222アリソンフィボナッチ

長い時間、問題の無い書き込み行列乗算最適化された再発は、非常にでこぼこ書きます。

まず、私たちが聞いて、すべてのは、ということです\(\ SUM私F_iとは、\) そして、このことは、再帰的にすることはできません。GMKはI + 1カンカンに私を教えています。

\((i+1)F_{i+1}=(i + 1)(F_i + F_{i -1})=iF_i + F_i + (i - 1)F_{i -1} + 2F_{i - 1}\)。这玩意就可以用矩阵啦。

この質問を書くことは過ちSBの束を作りました。

1.オーバーロードされた乗算は(返されませんでしたか?

ときに長い時間のために書かれた係数2 1曲2.遷移行列を書きます。

3.私の電源はすぐに、N-2からカウントを始め、1つの特別に刑を宣告されました。堅牢性の欠如

#include <bits/stdc++.h>
#define ll long long

ll n, p;

struct Matrix {
    ll a[10][10];
    Matrix() { memset(a, 0, sizeof(a)); }
    void QAQ() {
        a[1][1] = a[2][1] = a[3][1] = a[4][2] = a[1][3] = a[2][2] = a[2][4] = a[1][5] = a[5][5] = 1,
        a[4][1] = 2;
    }
    friend Matrix operator*(Matrix x, Matrix y) {
        Matrix z;
        for (int k = 1; k <= 5; k++)
            for (int i = 1; i <= 5; i++)
                for (int j = 1; j <= 5; j++) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
        return z;
    }
};

Matrix qpow(Matrix x, int b) {
    Matrix ret = x;
    for (; b; b >>= 1, x = x * x)
        if (b & 1)
            ret = ret * x;
    return ret;
}

signed main() {
    scanf("%lld%lld", &n, &p);
    if (n == 1) {
        puts("1");
        return 0;
    }
    Matrix tmp;
    tmp.QAQ();
    Matrix ans;
    ans.a[1][1] = 2, ans.a[1][2] = 1, ans.a[1][3] = ans.a[1][4] = 1, ans.a[1][5] = 1;
    tmp = qpow(tmp, n - 2);
    ans = ans * tmp;
    printf("%lld\n", ans.a[1][5]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/gekoo/p/11260676.html