Matrix Power Series(POJ 3233)

Problem 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

My Code

这题稍微麻烦点,如果直接算必然超时我这里用的方法是构造一个矩阵

|A,E|           |A,E|n        |An , E+A+A2+....+An-1|

|O,E|,因为|O,E|等于 |O ,           E               |,所以只要算出这个矩阵的k+1次,然后取这个矩阵的右上部分,再减去一个单位矩阵E就是S了,利用了一个分块矩阵的思想,学过线代的同学应该知道。

#include 
#include 
using namespace std;
int mod;
struct Matrix
{
    int M[70][70];          //矩阵扩充了4倍,所以这里要至少开60*60
};
Matrix mul(Matrix m1, Matrix m2, int n)
{
    Matrix m3;
    memset(m3.M, 0, sizeof(m3.M));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            for (int k = 0; k < n; k++)     //一定要加的时候就取模,否则会溢出
                m3.M[i][j] += (m1.M[i][k] * m2.M[k][j]) % mod;
            m3.M[i][j] %= mod;
        }
    return m3;
}

Matrix pow(Matrix m, int k, int n)
{
    Matrix ans;
    memset(ans.M, 0, sizeof(ans.M));
    for (int i = 0; i < n; i++)
        ans.M[i][i] = 1;
    while (k)
    {
        if (k & 1)
            ans = mul(ans, m, n);
        m = mul(m, m, n);
        k >>= 1;
    }
    return ans;
}
int main()
{
    int n, k;
    Matrix m;
    memset(m.M, 0, sizeof(m.M));
    cin >> n >> k >> mod;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            cin >> m.M[i][j];
            if (i == j)             //构造一个特殊的矩阵
            {
                m.M[i][j + n] = 1;
                m.M[i + n][j + n] = 1;
            }
        }
    m = pow(m, k + 1, 2 * n);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (i == j)
            {
                m.M[i][j + n]--;
                if (m.M[i][j + n] < 0)      //因为是先取模的,所以可能会有负的,要加回去
                    m.M[i][j + n] += mod;
            }
            cout << m.M[i][j + n] << ' ';
        }
        cout << endl;
    }
    return 0;
}