【POJ 3233】矩阵多项式和 - 快速幂

题目介绍:

Matrix Power Series
Time Limit: 3000MS   Memory Limit: 131072K
Total Submissions: 25225   Accepted: 10427

Description

Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.

Input

The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.

Output

Output the elements of S modulo m in the same way as A is given.

Sample Input

2 2 4
0 1
1 1

Sample Output

1 2
2 3
#include<vector>
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int MAX_N = 220;
int E[MAX_N][MAX_N];
int M;
class Mat {
public:
    Mat(int N, int N2) {
        vc.resize(N);
        for (int i = 0; i < N; i++) {
            vc[i].resize(N2);
        }
    }
    vector<int>& operator[](int idx) {
        return vc[idx];
    }
    int size() {
        return vc.size();
    }
private:
    vector<vector<int> > vc;
};
void multiply(Mat& CP, Mat& B, Mat& D) {
    memset(E, 0, sizeof(E));
    for (int i = 0; i < B.size(); i++) {
        for (int j = 0; j < B[0].size(); j++) {
            for (int k = 0; k < D.size(); k++) {
                // printf("prev, %d %d %d %d\n", E[i][j], B[i][k], D[k][j], B[i][k] * D[k][j]);
                E[i][j] = (E[i][j] + B[i][k] * (D[k][j] % M)) % M;
                // printf("last, %d %d %d %d\n", E[i][j], B[i][k], D[k][j], B[i][k] * D[k][j]);
            }
        }
    }
    for (int i = 0; i < B.size(); i++) {
        for (int j = 0; j < D[0].size(); j++) {
            CP[i][j] = E[i][j];
        }
    }
}

void debug(Mat& E, int N, int C) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < C; j++) {
            printf("%d ", E[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}
void mpow(Mat& B, int k) {
    int N = B.size();
    if (N == 0) {
        return;
    }
    int C = B[0].size();
    Mat cp(N, C);
    for (int i = 0; i < N; i++) {
        cp[i][i] = 1;
    }
    while (k) {
        if (k & 1) {
            // cp = cp * B^(2^k)
            multiply(cp, cp, B);
        }
        multiply(B, B, B);
        k = k >> 1;
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            B[i][j] = cp[i][j];
        }
    }
}
int main() {
    int n, k;
    int A[MAX_N][MAX_N];
    while (cin >> n >> k >> M) {
        Mat B(n * 2, n * 2);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> A[i][j];
            }
        }
        // copy Mat to be:
        // | A | 0 |
        // | I | I |
        // 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                B[i][j] = A[i][j];
            }
            B[n + i][i] = B[n + i][n + i] = 1;
        }
        mpow(B, k + 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int a = B[n + i][j] % M;
                if (i == j) a = (a + M - 1) % M;
                printf("%d%c", a, j == n - 1 ? '\n' : ' ');
            }
        }
    }
    return 0;
}

 

posted @ 2018-01-06 00:27  stackupdown  阅读(203)  评论(0编辑  收藏  举报