Loading [MathJax]/extensions/tex2jax.js

CH3401:石头游戏题解

毒瘤思路

对,这道题是毒瘤题。首先,我们可以判定出,这些序列一定会在\(60s\)内全部从头开始,因为\(1,2,3,4,5,6\)的最大公倍数为\(60\)。之后,我们可以考虑把这些操作放入操作矩阵之中。操作矩阵的长宽都为\(n*m\)。具体的操作对应如下:

  • 在本题中,我们把一个二维的点映射为一个数,公式为\(num(i,j)=(i-1)m+j\)。
  • 对于把格子值设置为数字的操作:
    1. 首先把操作矩阵\(A[0][num(i,j)]\)设置为操作数。
    2. 之后,把矩阵\(A[num(i,j)][num(i,j)]\)设置为\(1\),这是为了使其在矩阵乘法中得到保留。
  • 而对于移动操作:
    • 如果是\(E\),那么把\(A[num(i,j)][num(i,j+1)]\)设置为一,以此类推

然后算出\(p=\lfloor \frac{m}{60} \rfloor, q = m \mod 60\),进行矩阵快速幂和连续乘法即可。

好毒瘤,建议不要写。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// CH3401.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX_N = 70;
ll N, M, t, act;
char opt[MAX_N][MAX_N];
string opts[MAX_N];
struct matrix
{
ll mat[MAX_N][MAX_N], n, m;
matrix() { memset(mat, 0, sizeof(mat)); }
matrix(int n, int m)
{
this->n = n, this->m = m;
for (int i = 1; i <= max(n, m); i++)
mat[i][i] = 1;
}
matrix operator*(const matrix &tar) const
{
matrix ans = matrix();
ans.n = n, ans.m = tar.m;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= tar.m; j++)
for (int k = 0; k <= m; k++)
ans.mat[i][j] += mat[i][k] * tar.mat[k][j];
return ans;
}
matrix operator^(const int &tim) const
{
int ti = tim;
matrix ans, bas = *this;
for (int i = 0; i <= max(n, m); i++)
ans.mat[i][i] = 1;
ans.n = n, ans.m = m;
while (ti)
{
if (ti & 1)
ans = ans * bas;
bas = bas * bas;
ti >>= 1;
}
return ans;
}
} P, Q, mats[70];
ll getPos(ll x, ll y) { return (x - 1) * M + y; }
int main()
{
scanf("%lld%lld%lld%lld", &N, &M, &t, &act);
for (int i = 1; i <= N; i++)
for (int j = 1; j <= M; j++)
cin >> opt[i][j], opt[i][j] -= '0';
for (int i = 0; i < act; i++)
cin >> opts[i];
int p = t / 60, q = t % 60;
matrix F;
F.n = 0, F.m = getPos(N, M), F.mat[0][0] = 1;
for (int tim = 1; tim <= 60; tim++)
{
matrix current;
current.n = getPos(N, M), current.m = getPos(N, M);
current.mat[0][0] = 1;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= M; j++)
{
int pos = (tim - 1) % (opts[opt[i][j]].size());
char op = opts[opt[i][j]][pos];
switch (op)
{
case 'N':
if (i > 1)
current.mat[getPos(i, j)][getPos(i - 1, j)] = 1;
break;
case 'S':
if (i < N)
current.mat[getPos(i, j)][getPos(i + 1, j)] = 1;
break;
case 'E':
if (j < M)
current.mat[getPos(i, j)][getPos(i, j + 1)] = 1;
break;
case 'W':
if (j > 1)
current.mat[getPos(i, j)][getPos(i, j - 1)] = 1;
break;
case 'D':
break;
default:
current.mat[0][getPos(i, j)] = op - '0';
current.mat[getPos(i, j)][getPos(i, j)] = 1;
break;
}
}
mats[tim] = current;
}
P = mats[1];
for (int i = 2; i <= 60; i++)
P = P * mats[i];
P = P ^ p;
Q = q == 0 ? matrix(getPos(N, M), getPos(N, M)) : mats[1];
for (int i = 2; i <= q; i++)
Q = Q * mats[i];
F = F * P * Q;
ll ans = 0;
for (int i = 1; i <= getPos(N, M); i++)
ans = max(ans, F.mat[0][i]);
printf("%lld", ans);
return 0;
}
// CH3401.cpp #include <bits/stdc++.h> #define ll long long using namespace std; const int MAX_N = 70; ll N, M, t, act; char opt[MAX_N][MAX_N]; string opts[MAX_N]; struct matrix { ll mat[MAX_N][MAX_N], n, m; matrix() { memset(mat, 0, sizeof(mat)); } matrix(int n, int m) { this->n = n, this->m = m; for (int i = 1; i <= max(n, m); i++) mat[i][i] = 1; } matrix operator*(const matrix &tar) const { matrix ans = matrix(); ans.n = n, ans.m = tar.m; for (int i = 0; i <= n; i++) for (int j = 0; j <= tar.m; j++) for (int k = 0; k <= m; k++) ans.mat[i][j] += mat[i][k] * tar.mat[k][j]; return ans; } matrix operator^(const int &tim) const { int ti = tim; matrix ans, bas = *this; for (int i = 0; i <= max(n, m); i++) ans.mat[i][i] = 1; ans.n = n, ans.m = m; while (ti) { if (ti & 1) ans = ans * bas; bas = bas * bas; ti >>= 1; } return ans; } } P, Q, mats[70]; ll getPos(ll x, ll y) { return (x - 1) * M + y; } int main() { scanf("%lld%lld%lld%lld", &N, &M, &t, &act); for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) cin >> opt[i][j], opt[i][j] -= '0'; for (int i = 0; i < act; i++) cin >> opts[i]; int p = t / 60, q = t % 60; matrix F; F.n = 0, F.m = getPos(N, M), F.mat[0][0] = 1; for (int tim = 1; tim <= 60; tim++) { matrix current; current.n = getPos(N, M), current.m = getPos(N, M); current.mat[0][0] = 1; for (int i = 1; i <= N; i++) for (int j = 1; j <= M; j++) { int pos = (tim - 1) % (opts[opt[i][j]].size()); char op = opts[opt[i][j]][pos]; switch (op) { case 'N': if (i > 1) current.mat[getPos(i, j)][getPos(i - 1, j)] = 1; break; case 'S': if (i < N) current.mat[getPos(i, j)][getPos(i + 1, j)] = 1; break; case 'E': if (j < M) current.mat[getPos(i, j)][getPos(i, j + 1)] = 1; break; case 'W': if (j > 1) current.mat[getPos(i, j)][getPos(i, j - 1)] = 1; break; case 'D': break; default: current.mat[0][getPos(i, j)] = op - '0'; current.mat[getPos(i, j)][getPos(i, j)] = 1; break; } } mats[tim] = current; } P = mats[1]; for (int i = 2; i <= 60; i++) P = P * mats[i]; P = P ^ p; Q = q == 0 ? matrix(getPos(N, M), getPos(N, M)) : mats[1]; for (int i = 2; i <= q; i++) Q = Q * mats[i]; F = F * P * Q; ll ans = 0; for (int i = 1; i <= getPos(N, M); i++) ans = max(ans, F.mat[0][i]); printf("%lld", ans); return 0; }
// CH3401.cpp
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX_N = 70;
ll N, M, t, act;
char opt[MAX_N][MAX_N];
string opts[MAX_N];
struct matrix
{
    ll mat[MAX_N][MAX_N], n, m;
    matrix() { memset(mat, 0, sizeof(mat)); }
    matrix(int n, int m)
    {
        this->n = n, this->m = m;
        for (int i = 1; i <= max(n, m); i++)
            mat[i][i] = 1;
    }
    matrix operator*(const matrix &tar) const
    {
        matrix ans = matrix();
        ans.n = n, ans.m = tar.m;
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= tar.m; j++)
                for (int k = 0; k <= m; k++)
                    ans.mat[i][j] += mat[i][k] * tar.mat[k][j];
        return ans;
    }
    matrix operator^(const int &tim) const
    {
        int ti = tim;
        matrix ans, bas = *this;
        for (int i = 0; i <= max(n, m); i++)
            ans.mat[i][i] = 1;
        ans.n = n, ans.m = m;
        while (ti)
        {
            if (ti & 1)
                ans = ans * bas;
            bas = bas * bas;
            ti >>= 1;
        }
        return ans;
    }
} P, Q, mats[70];
ll getPos(ll x, ll y) { return (x - 1) * M + y; }
int main()
{
    scanf("%lld%lld%lld%lld", &N, &M, &t, &act);
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= M; j++)
            cin >> opt[i][j], opt[i][j] -= '0';
    for (int i = 0; i < act; i++)
        cin >> opts[i];
    int p = t / 60, q = t % 60;
    matrix F;
    F.n = 0, F.m = getPos(N, M), F.mat[0][0] = 1;
    for (int tim = 1; tim <= 60; tim++)
    {
        matrix current;
        current.n = getPos(N, M), current.m = getPos(N, M);
        current.mat[0][0] = 1;
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= M; j++)
            {
                int pos = (tim - 1) % (opts[opt[i][j]].size());
                char op = opts[opt[i][j]][pos];
                switch (op)
                {
                case 'N':
                    if (i > 1)
                        current.mat[getPos(i, j)][getPos(i - 1, j)] = 1;
                    break;
                case 'S':
                    if (i < N)
                        current.mat[getPos(i, j)][getPos(i + 1, j)] = 1;
                    break;
                case 'E':
                    if (j < M)
                        current.mat[getPos(i, j)][getPos(i, j + 1)] = 1;
                    break;
                case 'W':
                    if (j > 1)
                        current.mat[getPos(i, j)][getPos(i, j - 1)] = 1;
                    break;
                case 'D':
                    break;
                default:
                    current.mat[0][getPos(i, j)] = op - '0';
                    current.mat[getPos(i, j)][getPos(i, j)] = 1;
                    break;
                }
            }
        mats[tim] = current;
    }
    P = mats[1];
    for (int i = 2; i <= 60; i++)
        P = P * mats[i];
    P = P ^ p;
    Q = q == 0 ? matrix(getPos(N, M), getPos(N, M)) : mats[1];
    for (int i = 2; i <= q; i++)
        Q = Q * mats[i];
    F = F * P * Q;
    ll ans = 0;
    for (int i = 1; i <= getPos(N, M); i++)
        ans = max(ans, F.mat[0][i]);
    printf("%lld", ans);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *