poj 3233

http://poj.org/problem?id=3233
题目大意:给定矩阵A,求A + A^2 + A^3 + … + A^k的结果(两个矩阵相加就是对应位置分别相加)。输出的数据mod m。k<=10^9。
这道题两次二分,相当经典。首先我们知道,A^i可以二分求出。然后我们需要对整个题目的数据规模k进行二分。比如,当k=6时,有:
A + A^2 + A^3 + A^4 + A^5 + A^6 =(A + A^2 + A^3) + A^3*(A + A^2 + A^3)
应用这个式子后,规模k减小了一半。我们二分求出A^3后再递归地计算A + A^2 + A^3,即可得到原问题的答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
#define mem(x,y) memset(x,y,sizeof(x))
#define inf 0x3f3f3f3f
using namespace std;
#define siz 31
int n,k,mod;
struct matrix
{
int a[siz][siz];
matrix operator*(const matrix &y)const
{
matrix res;
mem(res.a,0);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(a[i][j])
for(int k=0;k<n;k++)
res.a[i][k]+=a[i][j]*y.a[j][k],res.a[i][k]%=mod;
return res;
}
matrix operator+(const matrix &y)const
{
matrix res;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
res.a[i][j]=a[i][j]+y.a[i][j],res.a[i][j]%=mod;
return res;
}
};
matrix qmod(matrix a,int k)
{

matrix res;
mem(res.a,0);
for(int i=0;i<n;i++)
res.a[i][i]=1;
while(k)
{
if(k&1)
res=res*a;
a=a*a;
k>>=1;
}
return res;
}
matrix bin(const matrix &a,int k)
{

if(k==1)
return a;
if(k&1)
return qmod(a,k)+bin(a,k-1);
int half=k/2;
matrix A=bin(a,half);
matrix B=qmod(a,half);
return A+A*B;
}
int main()
{

scanf("%d%d%d",&n,&k,&mod);
matrix a;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&a.a[i][j]);
a=bin(a,k);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
printf("%d%c",a.a[i][j]," \n"[j==n-1]);
}

EOF