POJ3233 Matrix Power Series 矩阵快速幂 矩阵中的矩阵

Matrix Power Series
Time Limit: 3000MS   Memory Limit: 131072K
Total Submissions: 27277   Accepted: 11143

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

Source

POJ Monthly--2007.06.03, Huang, Jinsong
 
题意: 这题就是求一个矩阵的和式:S(k),直接对和式建立递推:

A^i是一个矩阵

很显然,把每个A^i算出来是不行的,所以我们得找找关系

因为这里牵扯到了矩阵相加求和,所以我们可以想到构建一个包含A的矩阵(只要包含A和两个一就行,这样是为了最后能得到A^1+A^2+...+A^K的式子)

其中1是单位矩阵,单位矩阵是左对角线为1的矩阵

然后容易得到:

可以看出这个分块矩阵的左下角那块就可以得到要求的解S

我们取这一块,再减去一个单位矩阵1即可。

参考博客:https://www.cnblogs.com/pdev/p/4063669.html

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define debug(a) cout << #a << " " << a << endl
using namespace std;
const int maxn = 110;
const int mod = 2;
typedef long long ll;
struct matrix {
    ll a[maxn][maxn];
};
matrix base, ans;
ll n, t, m;
matrix multip( matrix x, matrix y ) {
    matrix tmp;
    for( ll i = 0; i < 2*n; i ++ ) {
        for( ll j = 0; j < 2*n; j ++ ) {
            tmp.a[i][j] = 0;
            for( ll k = 0; k < 2*n; k ++ ) {
                tmp.a[i][j] = ( tmp.a[i][j] + x.a[i][k] * y.a[k][j] ) % m;
            }
        }
    }
    return tmp;
}
void f( ll x ) {
    while( x ) {
        if( x&1 ) {
            ans = multip( ans, base );
        }
        base = multip( base, base );
        x /= 2;
    }
}
int main() {
    while( cin >> n >> t >> m ) {
        memset( ans.a, 0, sizeof(ans.a) );
        memset( base.a, 0, sizeof(base.a) );
        for( ll i = 0; i < n; i ++ ) {
            for( ll j = 0; j < n; j ++ ) {
                cin >> base.a[i][j];
            }
        }
        for( ll i = n; i < 2*n; i ++ ) { //两个单位矩阵
            base.a[i][i-n] = base.a[i][i] = 1;
        }
       //上面两个for循环是为了构建出新的包含A的矩阵
        for( ll i = 0; i < 2*n; i ++ ) {
            ans.a[i][i] = 1;
        }
        f(t+1);  //由上面举的例子可以看出要求出n次方,得算n+1次
        for( ll i = n; i < 2*n; i ++ ) {
            for( ll j = 0; j < n; j ++ ) {
                if( i == j+n ) {
                    ans.a[i][j] --;
                }
                if( j != n-1 ) {
                    cout << ( ans.a[i][j] + m ) % m << " ";
                } else {
                    cout << ( ans.a[i][j] + m ) % m << endl;
                }
            }
        }
    }
    return 0;
}
    

  

彼时当年少,莫负好时光。
原文地址:https://www.cnblogs.com/l609929321/p/9318746.html