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
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;
}