1. 程式人生 > >POJ3070 Fibonacci(矩陣快速冪加速遞推)【模板題】

POJ3070 Fibonacci(矩陣快速冪加速遞推)【模板題】

題目連結:傳送門

題目大意:

  求斐波那契數列第n項F(n)。

  (F(0) = 0, F(1) = 1, 0 ≤ n ≤ 109

思路:

  用矩陣乘法加速遞推。

演算法競賽進階指南的模板:

#include <iostream>
#include <cstring>

using namespace std;
const int MOD = 10000;

void mul(int f[2], int base[2][2]) {
    int c[2];
    memset(c, 0, sizeof c);
    for (int j = 0
; j < 2; j++) { for (int k = 0; k < 2; k++) { c[j] = (c[j] + 1LL * f[k] * base[k][j]) % MOD; } } memcpy(f, c, sizeof c); } void mulself(int base[2][2]) { int c[2][2]; memset(c, 0, sizeof c); for (int i = 0; i < 2; i++) for (int j = 0; j < 2
; j++) for (int k = 0; k < 2; k++) c[i][j] = (c[i][j] + 1LL*base[i][k]*base[k][j]) % MOD; memcpy(a, c, sizeof c); } int main() { int n; while (cin >> n && n != -1) { int f[2] = {0, 1}; int base[2][2] = {{0, 1}, {1, 1}}; for
(; n; n >>= 1) { if (n & 1) mul(f, base); mulself(base); } cout << f[0] << endl; } return 0; }
View Code

蒟蒻的模板:

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;
typedef long long ll;
const int MOD = 1e4;
const int MAXN = 2;
struct Matrix{
    int mat[MAXN][MAXN];
    Matrix operator * (Matrix const& b) const {
        Matrix res;
        memset(res.mat, 0, sizeof res.mat);
        for (int i = 0; i < MAXN; i++)
            for (int j = 0; j < MAXN; j++)
                for (int k = 0; k < MAXN; k++)
                    res.mat[i][j] = (res.mat[i][j] + this->mat[i][k] * b.mat[k][j])%MOD;
        return res;
    }
}base, F0, FN;
Matrix fpow(Matrix base, ll n) {
    Matrix res;
    memset(res.mat, 0, sizeof res.mat);
    for (int i = 0; i < MAXN; i++)
        res.mat[i][i] = 1;
    while (n) {
        if (n&1) res = res*base;
        base = base * base;
        n >>= 1;
    }
    return res;
}
void init()
{
    base.mat[0][0] = 0; base.mat[0][1] = 1;
    base.mat[1][0] = 1; base.mat[1][1] = 1;
    memset(F0.mat, 0, sizeof F0.mat);
    F0.mat[0][0] = 1; F0.mat[0][1] = 1;
}

int main()
{
    int N;
    while (cin >> N) {
        if (N == -1)
            break;
        init();
        FN = fpow(base, N);
        cout << FN.mat[0][1] << endl;
    }
    return 0;
}
View Code