LY1162 [ 20230323 CQYC省选模拟赛 T3 ] 跳!跳!跳!
题意#
给定 个长度为 的字符串,进行若干操作,求每个字符串 到 的方案数。
另外,你还有一个模式串 ,由 与 (通配符) 组成。
- 从 右边的串开始,不断向右移动,直到 与 匹配。
- 从 左边的串开始,不断向左移动,直到 与 匹配。
- 将 任意一个字符为 的位置改为 。从当前串开始,不断往右移动,直到 与 匹配。
- 将 任意一个字符改为 ,不移动。
Sol#
trivial 地,考虑如何用一个状态表示当前的 。
不难发现当前 一定和 匹配,那么我们只需要状压记录当前 哪些位置是 就行了。
考虑对于每个起点跑 。
前两个操作可以简单预处理,而第三个操作需要 的复杂度进行转移。
总复杂度为 。
直接卡常草过去。
Code#
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <queue>
#include <vector>
#include <bitset>
/* #define int long long */
#define pii pair <int, int>
#define il inline
#define rg register
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;
#endif
il int read() {
rg int p = 0, flg = 1;
rg char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') flg = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
p = p * 10 + c - '0';
c = getchar();
}
return p * flg;
}
void write(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x > 9) {
write(x / 10);
}
putchar(x % 10 + '0');
}
bool _stmer;
#define fi first
#define se second
const int N = 505, M = 6, K = 1 << 5;
array <array <int, M>, N> s;
array <array <int, K>, N> pre, suf;
il bool check(int T, int m, int x, int y){
rg bool flg = 1;
for (rg int k = 1; k <= m; k++)
if (!(T & (1 << (k - 1))))
flg &= (s[x][k] == s[y][k]);
return flg;
}
array <array <array <vector <int>, M>, K>, N> isl;
array <array <int, K>, N> dis;
queue <pii> q;
il void bfs(int st, int n, int m) {
for (int i = 1; i <= n; i++)
dis[i].fill(-1);
for (int i = 0; i < 1 << m; i++)
q.push(make_pair(st, i)), dis[st][i] = 0;
while (!q.empty()) {
rg pii u = q.front();
q.pop();
if (!~dis[pre[u.fi][u.se]][u.se])
dis[pre[u.fi][u.se]][u.se] = dis[u.fi][u.se] + 1, q.push(make_pair(pre[u.fi][u.se], u.se));
if (!~dis[suf[u.fi][u.se]][u.se])
dis[suf[u.fi][u.se]][u.se] = dis[u.fi][u.se] + 1, q.push(make_pair(suf[u.fi][u.se], u.se));
for (rg int i = 1; i <= m; i++) {
int tp = u.se ^ (1 << (i - 1));
if (!~dis[u.fi][tp])
dis[u.fi][tp] = dis[u.fi][u.se] + 1, q.push(make_pair(u.fi, tp)), tot++;
if (u.se & (1 << (i - 1))) continue;
for (auto t : isl[u.fi][u.se][i]) {
if (~dis[t][tp]) continue;
dis[t][tp] = dis[u.fi][u.se] + 1;
q.push(make_pair(t, tp));
}
}
}
}
array <array <int, N>, N> ans;
array <bitset <N>, M> vis;
bool _edmer;
int main() {
cerr << (&_stmer - &_edmer) / 1024.0 / 1024.0 << "MB\n";
/* freopen("string.in", "r", stdin); */
/* freopen("string.out", "w", stdout); */
rg int n = read(), m = read();
for (rg int i = 1; i <= n; i++)
for (rg int j = 1; j <= m; j++)
s[i][j] = read();
for (rg int i = 1; i <= n; i++) {
for (rg int T = 0; T < 1 << m; T++) {
for (rg int j = 1; j < n; j++) {
if (check(T, m, i, (i - j + n - 1) % n + 1)) {
pre[i][T] = (i - j + n - 1) % n + 1;
break;
}
}
for (rg int j = 1; j < n; j++) {
if (check(T, m, i, (i + j - 1) % n + 1)) {
suf[i][T] = (i + j - 1) % n + 1;
break;
}
}
for (rg int j = 1; j <= m; j++)
vis[j] = 0, vis[j][s[i][j]] = 1;
for (rg int j = 1; j < n; j++) {
rg int t = (i + j - 1) % n + 1;
for (rg int k = 1; k <= m; k++)
if (check(T, m, i, t) && (T & (1 << (k - 1))) && !vis[k][s[t][k]])
isl[t][T ^ (1 << (k - 1))][k].push_back(i), vis[k][s[t][k]] = 1;
}
}
}
for (rg int i = 1; i <= n; i++) {
bfs(i, n, m);
for (rg int j = 1; j <= n; j++)
ans[j][i] = dis[j][(1 << m) - 1];
}
for (rg int i = 1; i <= n; i++) {
for (rg int j = 1; j <= n; j++)
write(ans[i][j]), putchar(32);
puts("");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?