题目链接:http://poj.org/problem?id=3233
题目大意:给定一个n*n的方阵A,再给出k和m,问A^1 + A ^2 + A^3 + A... + A^k = ?矩阵中的每个数都对m取余。
解题思路:由A^k可用二分思想联想到这题也可以用二分思想,假设:如果k % 2 == 0,那么先计算A^1 + ... A^(k / 2),,然后可知A^((k/2)+1)等于A^1 * A^(k / 2),
A^((k/2)+2)等于A^2 * A^(k / 2),由此可得 A^1 + ... A^(k/2) = (A^1+...A^(k/2)) * ((A^(k/2) + E),后面+E表示(A^1+...A^(k/2)) * E.r如果k % 2 == 1,那么
A^1 + ... A^(k/2) = A^k + (A^k-1+..A^1);
测试数据:
2 2 4
0 1
1 1
2 1 1
0 1
1 2
2 2 10000
32768 32768
32768 32768
代码:
#include <stdio.h>
#include <string.h>
#define MAX 40
int n,m,arr[MAX][MAX];
struct Mat {
int mat[MAX][MAX],size;
Mat() {};
Mat(int n) {
size = n;
memset(mat,0,sizeof(mat));
}
Mat(int arr[][MAX],int n) {
size = n;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
mat[i][j] = arr[i][j];
}
friend Mat operator *(Mat a,Mat b);
friend Mat operator +(Mat a,Mat b);
friend Mat operator ^(Mat a,int k);
}E;
Mat operator *(Mat a,Mat b) {
Mat c(n);
for (int i = 0; i < c.size; ++i)
for (int j = 0; j < c.size; ++j)
for (int k = 0; k < c.size; ++k)
if (a.mat[i][k] && b.mat[k][j])
c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % m;
return c;
}
Mat operator +(Mat a,Mat b) {
Mat c(n);
for (int i = 0; i < c.size; ++i)
for (int j = 0; j < c.size; ++j)
c.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % m;
return c;
}
Mat operator ^(Mat a,int k) {
Mat c = E;
while (k) {
if (k & 1) c = c * a;
a = a * a,k >>= 1;
}
return c;
}
Mat sum(Mat A,int k) {
if (k == 1) return A;
if (k & 1) return sum(A,k-1) + (A^k);
return sum(A,k/2) * ((A^(k / 2)) + E);
}
int main()
{
int i,j,k;
while (scanf("%d%d%d",&n,&k,&m) != EOF) {
E.size = n;
memset(E.mat,0,sizeof(E.mat));
for (i = 0; i < E.size; ++i)
E.mat[i][i] = 1;
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
scanf("%d",&arr[i][j]),arr[i][j] %= m;
Mat c(arr,n);
c = sum(c,k);
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
printf(j == n - 1? "%d\n" : "%d ",c.mat[i][j]%m);
}
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。