https://www.acwing.com/problem/content/208/
因为1~6的最小公倍数是60,所以以60为周期进行快速幂然后剩下的算余项,注意两点:
1、递推矩阵永远有这样的形式:
A=A*B
其中A就是用来把各步的递推结果压缩保存的矩阵(仿照快速幂)
2、越界的石子直接消失了,原题没说明要怎么处理
3、计算的过程会溢出
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 10000007;
struct Matrix {
static const int MAXN = 65;
ll ma[MAXN][MAXN];
Matrix() {
//init();
}
void init() {
memset(ma, 0, sizeof(ma));
}
void setE() {
init();
for(int i = 0; i < MAXN; ++i)
ma[i][i] = 1;
}
Matrix operator+(const Matrix &m)const {
Matrix Tmp;
Tmp.init();
for(int i = 0; i < MAXN; ++i) {
for(int j = 0; j < MAXN; ++j)
Tmp.ma[i][j] = ma[i][j] + m.ma[i][j];
}
return Tmp;
}
Matrix operator*(const Matrix &m)const {
Matrix Tmp;
Tmp.init();
for(int k = 0; k < MAXN; ++k) {
for(int i = 0; i < MAXN; ++i) {
register ll r = ma[i][k];
for(int j = 0; j < MAXN; ++j)
Tmp.ma[i][j] += r * m.ma[k][j];
}
}
return Tmp;
}
void show(int n) {
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
printf("%2d ", ma[i][j]);
}
puts("");
}
puts("---");
}
} tma[60], Tma, F;
Matrix qpow(Matrix x, ll n) {
Matrix res;
res.setE();
while(n) {
if(n & 1)
res = res * x;
x = x * x;
n >>= 1;
}
return res;
}
char ins[8][9];
char ins2[10][7];
int n, m;
void _setins(int i, int j, int ti, char op) {
if(op >= '0' && op <= '9') {
tma[ti].ma[i * m + j][i * m + j] = 1;
tma[ti].ma[i * m + j][n * m] = op - '0';
} else if(op == 'D') {
tma[ti].ma[i * m + j][i * m + j] = 0;
} else if(op == 'N') {
tma[ti].ma[i * m + j][i * m + j] = 0;
if(i > 0) {
tma[ti].ma[(i - 1)*m + j][i * m + j] = 1;
}
} else if(op == 'W') {
tma[ti].ma[i * m + j][i * m + j] = 0;
if(j > 0) {
tma[ti].ma[i * m + j - 1][i * m + j] = 1;
}
} else if(op == 'S') {
tma[ti].ma[i * m + j][i * m + j] = 0;
if(i + 1 < n) {
tma[ti].ma[(i + 1)*m + j][i * m + j] = 1;
}
} else {
tma[ti].ma[i * m + j][i * m + j] = 0;
if(j + 1 < m) {
tma[ti].ma[i * m + j + 1][i * m + j] = 1;
}
}
}
void setins(int i, int j) {
int insid = (ins[i][j] - '0');
char *op = ins2[insid];
int len = strlen(op);
int cur = 0;
for(int ti = 0; ti < 60; ++ti) {
_setins(i, j, ti, op[cur]);
++cur;
if(cur == len)
cur = 0;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
ll T;
int act;
while(~scanf("%d%d%lld%d", &n, &m, &T, &act)) {
for(int i = 0; i < n; ++i)
scanf("%s", ins[i]);
for(int a = 0; a < act; ++a) {
scanf("%s", ins2[a]);
}
for(int i = 0; i < 60; ++i) {
tma[i].init();
tma[i].ma[n * m][n * m] = 1;
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < m; ++j)
setins(i, j);
}
/*for(int i = 0; i < 1; ++i) {
tma[i].show(n * m + 1);
}*/
Tma.setE();
for(int i = 0; i < 60; ++i)
Tma = tma[i] * Tma;
ll T1 = T / 60;
Tma = qpow(Tma, T1);
ll T2 = T % 60;
for(int i = 0; i < T2; ++i) {
Tma = tma[i] * Tma;
//Tma.show(n * m + 1);
}
F.init();
F.ma[n * m][0] = 1;
//F.show(n * m + 1);
F = Tma * F;
//F.show(n * m + 1);
ll maxans = 0;
for(int i = 0; i < n * m; ++i) {
maxans = max(maxans, F.ma[i][0]);
}
printf("%lld
", maxans);
}
}