专栏文章

题解:AT_abc425_f [ABC425F] Inserting Process

AT_abc425_f题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minrgjvy
此快照首次捕获于
2025/12/02 07:08
3 个月前
此快照最后确认于
2025/12/02 07:08
3 个月前
查看原文
N22N\le 22,显然是状压 dp。根据套路,使用二进制第 ii 位来代表 TT 的第 ii 位选没选。
状态转移方程?注意到可能有重复计数(多个前驱状态代表的字符串相同但是掩码不同),需要去重。这里使用一个数组记录每个状态的最小与其代表字符串相同的状态编号,使用这个来计算,然后使用 STL 的 setunordered_set 去重即可。虽然 set 会多一个 log\log,但是实际上因为 NN 很小所以和 unordered_set 差距不大。
差评:本机样例三 9s9\mathrm{s},提交过了。
代码&提交记录CPP
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>

using namespace std;

int f[(1 << 22) + 5];
int lst[(1 << 22) + 5];

int main()
{
	int n;
	scanf("%d", &n);
	string str;
	cin >> str;
	f[0] = 1;
	for (int i = 1; i < (1 << n); i++)
	{
		vector<int> vt;
		for (int j = 0; j < n; j++)
		{
			if (i & (1 << j)) vt.push_back(j);
		}
		int sum = 0, cur = 0;
		for (int j = 0; j < n; j++)
		{
			if (cur < vt.size() && str[j] == str[vt[cur]])
			{
				sum += (1 << j);
				cur++;
			}
		}
		lst[i] = sum;
		set<int> us;
		for (int j : vt)
		{
			us.insert(lst[i ^ (1 << j)]);
		}
		for (int x : us)
		{
			f[i] = (f[i] + f[x]) % 998244353;
		}
	}
	printf("%d\n", f[(1 << n) - 1]);
	return 0;
}
sub

评论

0 条评论,欢迎与作者交流。

正在加载评论...