Wiki_ki

导航

POJ 3233 Matrix Power Series

  题目的意思是已知一个n阶矩阵A,以及K,M,求S = A + A^2 + A^3 + ... + A^K,由于里面的数值当K很大时偏大,对M取模。其中数据的范围为:

   n (n ≤ 30), k (k ≤ 109) and m (m < 104). 

  构造分块矩阵 B = A  I

            0  I

  由数学归纳法可证得 B^(K+1)= A^K  I+A^1+A^2+...+A^K

                  0     I

  这样这道题目就纯粹转化为了求B矩阵的K+1次方了,二分即可。

  代码如下:

#include <iostream>

#define MAXN 61

using namespace std;

int NN , N , M , K , temp;
int a[MAXN][MAXN] , ans[MAXN][MAXN];
int b[32][MAXN][MAXN] , u[31];

void    init(int T) {
    memset(b,0,sizeof(b));
    for (int i = 0;i < NN;i++)
        for (int j = 0;j < NN;j++)
            b[1][i][j] = a[i][j];
    u[1] = 1; temp = 1;
    while (u[temp]*2 < T) {
        temp ++;
        u[temp] = u[temp-1] * 2;
        for (int k = 0;k < NN;k++)
            for (int i = 0;i < NN;i++)
                for (int j = 0;j < NN;j++) {
                    b[temp][i][j] += (b[temp-1][i][k] * b[temp-1][k][j]) % M;
                    b[temp][i][j] %= M;
                }
    }
    memset(ans,0,sizeof(ans));
    for (int i = 0;i < NN;i++)  ans[i][i] = 1;
}

void    calc(int T) {
    int bak[MAXN][MAXN];
    while (T) {
        while (T < u[temp]) temp --;
        memcpy(bak,ans,sizeof(bak));
        memset(ans,0,sizeof(ans));
        for (int k = 0;k < NN;k++)
            for (int i = 0;i < NN;i++)
                for (int j = 0;j < NN;j++) {
                    ans[i][j] += (bak[i][k] * b[temp][k][j]) % M;
                    ans[i][j] %= M;
                }
        T -= u[temp];
    }
    for (int i = 0;i < NN;i++)
      ans[i][i+N] = (ans[i][i+N] - 1 + M) % M;
}

int main () {
    memset(a,0,sizeof(a));
    cin >> N >> K >> M;
    for (int i = 0;i < N;i++)
        for (int j = 0;j < N;j++)
            cin >> a[i][j];
    NN = N*2;
    for (int i = 0;i < N;i++)
        a[i][i+N] = 1;
    for (int i = N;i < NN;i++)
        a[i][i] = 1;
    memcpy(ans,a,sizeof(a));
    init(K+1);
    calc(K+1);
    for (int i = 0;i < N;i++) {
        for (int j = N;j < NN-1;j++)
            cout << ans[i][j] << " ";
        cout << ans[i][NN-1] << endl;
    }
    return 0;
}

  测试结果如下:

posted on 2012-07-27 15:21  Wiki_ki  阅读(148)  评论(0编辑  收藏  举报