ACM题集:https://blog.csdn.net/weixin_39778570/article/details/83187443
题目链接:http://poj.org/problem?id=3233
Given a n × n matrix A and a positive integer k, find the sum S = A + A 2 + A 3 + … + A k S = A + A^2+ A^3+ … + A^k S=A+A2+A3+…+Ak.
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 the elements of S modulo m in the same way as A is given.
求a的前n次幂缀和矩阵可以这么构造
| a^1, 1 |^(n) | a^n, a^0+a^1+a^2+...+a^(n-1) |
| 0 , 1 | =======> | 0 , 1 |
同理,求矩阵A的前n次幂的前缀和也可以使用相同的方法构造
| A^1, A^0 |^(n) | A^n, A^0+A^1+A^2+...+A^(n-1) |
| 0 , A^0 | =======> | 0 , A^0 |
这里的A^0是单位矩阵
#include
#include
#include
#include
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int N=62; // 注意要开两倍大
int n,k,mod;
struct mat{
int mp[N][N],len;
mat(int x){
len = x;memset(mp, 0, sizeof(mp));
}
mat friend operator *(mat a, mat b){
mat ret(a.len);
// k,i,j比ijk更快!
fo(k,1,ret.len)
fo(i,1,ret.len)
fo(j,1,ret.len)
ret.mp[i][j] = (ret.mp[i][j] + a.mp[i][k]*b.mp[k][j]) % mod;
return ret;
}
mat friend operator ^(mat a, int n){
mat ret(a.len);
for(int i=1; i<=ret.len; i++)ret.mp[i][i] = 1;
while(n){
if(n&1)ret = ret*a;
a = a*a;
n>>=1;
}
return ret;
}
void debug(){
for(int i=1; i<=len; i++){
for(int j=1; j<=len; j++){
printf("%d%c",mp[i][j],j==len?'\n':' ');
}
}
}
};
int main(){
scanf("%d%d%d",&n,&k,&mod);
// 构造矩阵
mat A(n+n);
fo(i,1,n)fo(j,1,n)scanf("%d",&A.mp[i][j]);
fo(i,1,n)A.mp[i][i+n] = A.mp[i+n][i+n] = 1;
// 计算
A = A^(k+1);
fo(i,1,n)A.mp[i][i+n]=(A.mp[i][i+n]-1+mod)%mod; // 减去A^0
// 输出
fo(i,1,n)fo(j,1,n)
printf("%d%c",A.mp[i][j+n],j==n?'\n':' ');
return 0;
}