>Link
POJ 3233
>Description
给出一个 n ∗ n n*n n∗n的矩阵 A A A,求出模 m m m的情况下 S n = A + A 1 + A 2 + . . . + A n S_n=A+A^1+A^2+...+A^n Sn=A+A1+A2+...+An
>解题思路
我们先考虑不是矩阵的情况,很容易推出求
s
n
s_n
sn如下
[
a
n
−
1
s
n
−
2
]
→
[
a
n
(
a
n
−
1
∗
a
)
s
n
−
1
(
s
n
−
2
+
a
n
−
1
)
]
\begin{bmatrix} a^{n-1} & s_{n-2} \end{bmatrix} → \begin{bmatrix} a^n(a^{n-1}*a) & s_{n-1}(s_{n-2}+a^{n-1}) \end{bmatrix}
[an−1sn−2]→[an(an−1∗a)sn−1(sn−2+an−1)]
所以 B B B矩阵应为 [ a 1 0 1 ] \begin{bmatrix} a &1 \\ 0 & 1 \end{bmatrix} [a011]
但是
a
a
a和
s
s
s实际上是矩阵,我们要求的是
[
A
n
−
1
S
n
−
2
]
→
[
A
n
(
A
n
−
1
∗
A
)
S
n
−
1
(
S
n
−
2
+
A
n
−
1
)
]
\begin{bmatrix} A^{n-1} & S_{n-2} \end{bmatrix} → \begin{bmatrix} A^n(A^{n-1}*A) & S_{n-1}(S_{n-2}+A^{n-1}) \end{bmatrix}
[An−1Sn−2]→[An(An−1∗A)Sn−1(Sn−2+An−1)]
其实可以把
B
B
B矩阵扩大,也就是把
a
a
a和
1
1
1和
0
0
0置换成等价的
n
∗
n
n*n
n∗n大小的
X
X
X矩阵
a:正常操作,
A
∗
X
=
A
2
A*X=A^2
A∗X=A2,所以
X
X
X与
A
A
A相同
1:一个矩阵乘上另一个矩阵
X
X
X与原本的相同,可推出
X
X
X矩阵的对角线为1,其余全为0
0:一个矩阵乘上一个矩阵为0,所以
X
X
X矩阵为全为0的矩阵
最后加进去,
B
B
B矩阵变成:
[
[
a
1
,
1
a
1
,
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
a
n
,
n
]
[
1
0
.
.
.
0
1
.
.
.
0
.
.
.
1
]
[
0
0
0
.
.
.
.
.
.
.
.
.
0
0
0
]
[
1
0
.
.
.
0
1
.
.
.
0
.
.
.
1
]
]
\begin{bmatrix} \begin{bmatrix} a_{1,1} & a_{1,2} &... \\ ...& ... &... \\ ... &... & a_{n,n} \end{bmatrix} & \begin{bmatrix} 1 & 0 &... \\ 0 &1 &... \\ 0&... & 1 \end{bmatrix}\\ \begin{bmatrix} 0 &0 &0 \\ ... & ... & ...\\ 0 &0 & 0 \end{bmatrix} & \begin{bmatrix} 1 & 0 &... \\ 0 &1 &... \\ 0&... & 1 \end{bmatrix} \end{bmatrix}
⎣⎢⎢⎢⎢⎢⎢⎡⎣⎡a1,1......a1,2............an,n⎦⎤⎣⎡0...00...00...0⎦⎤⎣⎡10001.........1⎦⎤⎣⎡10001.........1⎦⎤⎦⎥⎥⎥⎥⎥⎥⎤
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
struct matrix
{
int x, y;
LL a[70][70];
} A, B, ans;
LL m;
matrix operator *(matrix a, matrix b)
{
matrix c;
c.x = a.x, c.y = b.y;
for (int i = 1; i <= c.x; i++)
for (int j = 1; j <= c.y; j++) c.a[i][j] = 0;
for (int k = 1; k <= a.y; k++)
for (int i = 1; i <= c.x; i++)
for (int j = 1; j <= c.y; j++)
c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % m) % m;
return c;
}
void power (LL k)
{
if (k == 1) {B = A; return;}
power (k >> 1);
B = B * B;
if (k & 1) B = B * A;
}
int main()
{
int n;
LL k;
scanf ("%d%lld%lld", &n, &k, &m);
ans.x = n, ans.y = 2 * n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf ("%lld", &ans.a[i][j]), ans.a[i][j] %= m;
A.x = A.y = 2 * n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) A.a[i][j] = ans.a[i][j];
for (int i = 1; i <= n; i++)
A.a[i][i + n] = A.a[i + n][i + n] = 1;
power (k);
ans = ans * B;
for (int i = 1; i <= n; i++)
{
for (int j = n + 1; j <= 2 * n; j++)
printf ("%lld ", ans.a[i][j]);
printf ("\n");
}
return 0;
}