uva 10870 - Recurrences(矩阵快速幂)

题目链接:uva 10870 - Recurrences

题目大意:考虑线性递推,给出递推方程,求f(n)%m.

解题思路:矩阵快速幂。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxsize = 100;
typedef long long ll;
typedef long long type;

type MOD;

struct Mat {
    int r, l;
    type arr[maxsize][maxsize];

    Mat (int r = 0, int l = 0) { 
        set(r, l);
        memset(arr, 0, sizeof(arr));
    }

    void set (int r, int l) {
        this->r = r;
        this->l = l;
    }

    Mat operator * (const Mat& u) {
        Mat ret(r, u.l);
        for (int k = 0; k < l; k++) {
            for (int i = 0; i < r; i++)
                for (int j = 0; j < u.l; j++)
                    ret.arr[i][j] = (ret.arr[i][j] + arr[i][k] * u.arr[k][j]) % MOD;
        }
        return ret;
    }
};

void put (Mat x) {
    for (int i = 0; i < x.r; i++) {
        for (int j = 0; j < x.l; j++)
            printf("%lld ", x.arr[i][j]);
        printf("\n");
    }
}

Mat pow_mat (Mat ans, Mat x, ll n, ll m) {
    MOD = m;

    while (n) {
        if (n&1)
            ans = x * ans;
        x = x * x;
        n >>= 1;
    }
    return ans;
}


int main () {
    int D;
    ll N, M;
    while (scanf("%d%lld%lld", &D, &N, &M) == 3 && D + N + M) {
        Mat x(D, D);
        for (int i = 1; i < D; i++)
            x.arr[i-1][i] = 1;
        for (int i = 0; i < D; i++) {
            scanf("%lld", &x.arr[D-1][D-1-i]);
            x.arr[D-1][D-1-i] %= M;
        }

        Mat ans(D, 1);
        for (int i = 0; i < D; i++) {
            scanf("%lld", &ans.arr[i][0]);
            ans.arr[i][0] %= M;
        }

        if (N > D) {
            Mat tmp = pow_mat(ans, x, N - D, M);
            printf("%lld\n", tmp.arr[D-1][0]);
        } else
            printf("%lld\n", ans.arr[N-1][0]);
    }
    return 0;
}

你可能感兴趣的:(uva 10870 - Recurrences(矩阵快速幂))