ABC419 补题

赛后补的111

A

人机验证题。


#include <bits/stdc++.h>
//#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}
	
	inline void write(int x) {
		int top = 0;
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}
	
	inline void print(int x, char ch) {
		write(x), putchar(ch);
	}
#endif 

string s;

signed main() {
	cin >> s;
	if (s == "red") 
		cout << "SSS\n";
	else if (s == "blue")
		cout << "FFF\n";
	else if (s == "green")
		cout << "MMM\n";
	else
		cout << "Unknown\n";
	return 0;
}

B

小根堆直接做。

#include <bits/stdc++.h>
#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}

	inline void write(int x) {
		int top = 0;
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}

	inline void print(int x, char ch) {
		write(x), putchar(ch);
	}
#endif

int Q;
priority_queue<int, vector<int>, greater<int>> q;

signed main() {
	Q = read();
	for (int _ = 1; _ <= Q; _ ++) {
		int opt = read(), x;
		if (opt == 1) {
			x = read();
			q.push(x);
		}
		else 
			print(q.top(), '\n'), q.pop();
	}
	return 0;
}

C

首先你发现每个点可以单独考虑,那么取最平均的点即可。

#include <bits/stdc++.h>
#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}

	inline void write(int x) {
		int top = 0;
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}

	inline void print(int x, char ch) {
		write(x), putchar(ch);
	}
#endif

constexpr int N = 2e5 + 100;
int n, mxx, mxy, mnx, mny;

signed main() {
	n = read();
	mxx = mxy = -1;
	mnx = mny = 1e9 + 7;
	for (int i = 1, x, y; i <= n; i ++) {
		x = read(), y = read();
		mxx = max(mxx, x), mnx = min(mnx, x);
		mxy = max(mxy, y), mny = min(mny, y);
	}
	int ans = max(ceil((mxx - mnx) / 2.0), ceil((mxy - mny) / 2.0));
	print(ans, '\n');
	return 0;
}

D

你发现只需要考虑每个位置的交换次数的奇偶性即可。

偶则为原来的,奇则为另一个。

#include <bits/stdc++.h>
//#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}

	inline void write(int x) {
		int top = 0;
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}

	inline void print(int x, char ch) {
		write(x), putchar(ch);
	}
#endif

constexpr int N = 5e5 + 100;
int n, m, d[N];
string s, t;

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> m >> s >> t;
	s = " " + s, t = " " + t;
	for (int _ = 1, L, R; _ <= m; _ ++) {
		cin >> L >> R;
		d[L] ++, d[R + 1] --;
	}
	
	for (int i = 1; i <= n; i ++)
		d[i] += d[i - 1];
	for (int i = 1; i <= n; i ++) {
		if (!(d[i] & 1))
			cout << s[i];
		else
			cout << t[i];
	}
	return 0;
}

E

数据范围很 \(O(n^3)\) 啊,考虑 dp。

你发现如果想直接 dp 需要考虑的状态数较多,考虑找一点性质。

我们最后的情况是 \(sum_{[i,i + L - 1]} \bmod m = 0\),那么就是 \(sum_{[i,i+L-1]} \equiv sum_{[i+1,i+L]} (\bmod \enspace m)\),即可得到 \(a_i \equiv a_{i+L}(\mod \enspace m)\)

考虑记 \(val_{i,j}\) 表示对于所有模 \(L\) 等于 \(i\) 的下标位置的 \(a_i\) 使得其模 \(m\) 等于 \(j\) 的最小操作次数,则有 \(\forall j = ki(k \geq 0) \land j < n,val_{j,(a_j + k) \bmod m} \leftarrow val_{j,(a_j + k) \bmod m} + k\)

那么考虑记 \(f_{i,j}\) 表示考虑了前 \(i\) 个和模 \(m\)\(j\) 的最小操作次数。

那么我们只需要考虑前 \(L\) 个就行,因为确定了前 \(L\) 个就确定了整个数组。

则有方程:

\[f_{i,j + k} = \min\{f_{i-1,j} + val_{i,k}\} \]

答案则为 \(\min\{f_{n,0}\}\)

#include <bits/stdc++.h>
#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)

	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}
#endif
constexpr int N = 510;
int n, m, L;
int a[N], val[N][N];
int f[N], g[N];

signed main() {
	n = read();
	m = read();
	L = read();
	for (int i = 0; i < n; i ++)
		a[i] = read();
	for (int i = 0; i < L; i ++) {
		for (int j = i; j < n; j += L) {
			for (int k = 0; k < m; k ++) 
				val[i][(a[j] + k) % m] += k;
		}
	}
	
	memset(f, 0x3f, sizeof(f));
	f[0] = 0;
	for (int i = 0; i < L; i ++) {
		memset(g, 0x3f, sizeof(g));
		for (int j = 0; j < m; j ++) {
			for (int k = 0; k < m; k ++) 
				g[(j + k) % m] = min(g[(j + k) % m], f[j] + val[i][k]);
		}
		memcpy(f, g, sizeof(f));
	}
	printf("%lld\n", f[0]);
	return 0;
}

F

显然的 ACAM。

但是需要状压 dp。

\(f_{i,j,st}\) 表示考虑到了第 \(i\) 位,在 ACAM 上 \(j\) 节点,字符串选择状态 \(st\) 的方案数,最后答案为 \(\sum\limits_{i=0}^{siz}{f_{L,i,U}}\),其中 \(siz\) 为 ACAM 大小,\(U\) 为全集。

那么还需要再字符串末尾记以该节点结尾的总状态,同时在 \(fail\) 链顶记总状态。

转移:\(\forall k \in son_j,f_{i,k,st\mid val_k} \leftarrow f_{i,k,st\mid val_k} + f_{i,j,st}\)

#include <bits/stdc++.h>
//#define FASTIO
#define int long long
#define son(rt,x) acam[rt].son[x]
#define fail(rt) acam[rt].fail
#define val(rt) acam[rt].val
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}

	inline void write(int x) {
		int top = 0;
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}

	inline void print(int x, char ch) {
		write(x), putchar(ch);
	}
#endif

constexpr int N = 110;
constexpr int M = (1 << 8) + 5;
constexpr int mod = 998244353;
int n, L, cnt;
string s;
int f[N][N][M];

struct ACAM {
	int fail;
	int son[26];
	int val;
} acam[N];

inline void ins(string str, int id) {
	int now = 0;
	for (int i = 0; i < (int)str.length(); i ++) {
		int chVal = str[i] - 'a';
		if (!son(now, chVal))
			son(now, chVal) = ++cnt;
		now = son(now, chVal);
	}
	val(now) |= (1 << id);
}

inline void get() {
	queue<int> q;
	for (int ch = 0; ch < 26; ch ++) {
		if (son(0, ch)) 	
			q.push(son(0, ch));
	}
	
	while (!q.empty()) {
		int now = q.front();
		q.pop();
		val(now) |= val(fail(now));
		for (int ch = 0; ch < 26; ch ++) {
			if (!son(now, ch)) 
				son(now, ch) = son(fail(now), ch);
			else {
				fail(son(now, ch)) = son(fail(now), ch);
				q.push(son(now, ch));
			}
		}
	}
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> L;
	for (int i = 0; i < n; i ++)
		cin >> s, ins(s, i);
	get();
	const int U = (1 << n) - 1;
	f[0][0][0] = 1;
	for (int i = 1; i <= L; i ++) {
		for (int now = 0; now <= cnt; now ++) {
			for (int st = 0; st <= U; st ++) {
				for (int ch = 0; ch < 26; ch ++) {
					int j = son(now, ch);
					f[i][j][st | val(j)] = (f[i][j][st | val(j)] + f[i - 1][now][st]) % mod;
				}
			}
		}
	}
	
//	for (int now = 0; now <= cnt; now ++)
//		cout << f[L][now][U] << ' ';
//	cout << '\n';
			
	int ans = 0;
	for (int now = 0; now <= cnt; now ++)
		ans = (ans + f[L][now][U]) % mod;
	cout << ans << '\n';
	return 0;
}

posted @ 2025-08-17 16:53  xAlec  阅读(16)  评论(0)    收藏  举报