LY1162 [ 20230323 CQYC省選模擬賽 T3 ] 跳!跳!跳!

cxqghzj發表於2024-03-06

題意

給定 \(n\) 個長度為 \(m\) 的字串,進行若干操作,求每個字串 \(S_a\)\(S_b\) 的方案數。

另外,你還有一個模式串 \(T\),由 \({1, ..., n}\)\(0\)(萬用字元) 組成。

  • \(S_x\) 右邊的串開始,不斷向右移動,直到 \(S_y\)\(T\) 匹配。
  • \(S_x\) 左邊的串開始,不斷向左移動,直到 \(S_y\)\(T\) 匹配。
  • \(T\) 任意一個字元為 \(0\) 的位置改為 \({1, ..., n}\)。從當前串開始,不斷往右移動,直到 \(S_y\)\(T\) 匹配。
  • \(T\) 任意一個字元改為 \(0\),不移動。

\(m \le 5, n \le 500\)

Sol

trivial 地,考慮如何用一個狀態表示當前的 \(T\)

不難發現當前 \(T\) 一定和 \(S_x\) 匹配,那麼我們只需要狀壓記錄當前 \(T\) 哪些位置是 \(0\) 就行了。

考慮對於每個起點跑 \(bfs\)

前兩個操作可以簡單預處理,而第三個操作需要 \(n \times m\) 的複雜度進行轉移。

總複雜度為 \(n ^ 3 2 ^ m m\)

直接卡常草過去。

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;
}

相關文章