专栏文章

题解:AT_agc020_e [AGC020E] Encoding Subsets

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

文章操作

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

当前评论
0 条
当前快照
1 份
快照标识符
@minm6rg7
此快照首次捕获于
2025/12/02 04:41
3 个月前
此快照最后确认于
2025/12/02 04:41
3 个月前
查看原文

题目大意

一个长度为 nn0101ss 的压缩方案数。
1n1001 \le n \le 100

题目分析

记号说明

对于两个字符串 sstt,其中 ttss子串
  1. sts - t 为在 ss 中去掉 tt 后的字符串。
  2. 对于一个正整数 kkk×tk \times t 表示 kktt 拼接起来。

分析

f(s)f(s) 代表 ss 的压缩方案数。
考虑转移。对于 ss 的最后一个字符 cc,有两种情况:
  1. cc 不参与压缩时:
    • c=0c = 0 时,f(s)=f(sc)f(s) = f(s - c)
    • c=1c = 1 时,f(s)=f(sc)×2f(s) = f(s - c) \times 2,因为可以 101 \to 0
  2. cc 参与压缩时:我们可以 O(n2)\mathcal{O}(n ^ 2) 暴力枚举 cc 要被压缩的最后一段。
    设压缩的字符串为 tt,压缩了 kk 个,那么 f(s)=f(t)f(st×k)f(s) = f(t) * f(s - t \times k)
由于状态数远远达不到上界,所以可以使用 记忆化搜索,时间复杂度 O(能过)\mathcal{O}(能过)
因为 n100n \le 100,我们可以用 __int128 来表示 0101 串。

code

CPP
#include <bits/stdc++.h>
#define ft first
#define sd second
#define endl '\n'
#define pb push_back
#define md make_pair
#define gc() getchar()
#define pc(ch) putchar(ch)
#define umap unordered_map
#define pque priority_queue
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
typedef __int128 bint;
typedef pair<int, int> pii;
typedef pair<pii, int> pi1;
typedef pair<pii, pii> pi2;
const ll INF = 0x3f3f3f3f;
const db Pi = acos(-1.0);
inline ll read()
{
	ll res = 0, f = 1; char ch = gc();
	while (ch < '0' || ch > '9') f = (ch == '-' ? -1 : f), ch = gc();
	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + (ch ^ 48), ch = gc();
	return res * f;
}
inline void write(ll x)
{
	if (x < 0) x = -x, pc('-');
	if (x > 9) write(x / 10);
	pc(x % 10 + '0');
}
inline void writech(ll x, char ch) { write(x), pc(ch); }
const ll mod = 998244353;
const int N = 1e2 + 5;
map<bint, ll> dp[N];
void Add(ll &a, ll b) { a += b, a %= mod; }
ll dfs(int n, bint s)
{
	if (n == 0) return 1;
	if (dp[n].count(s)) return dp[n][s];
	// c 不参与压缩
	ll res = dfs(n - 1, s >> 1) * ((s & 1) + 1) % mod; 
	// f(s) = f(s - c),     c = 0
	//        f(s - c) * 2, c = 1
	bint tmp = 0, t = 0;
	for (int i = 1; i <= n; i++) // i 是 t 的长度 
	{
		tmp = (tmp << 1) | 1;
		t = s & tmp;
		for (int j = i * 2; j <= n; j += i) // 看一下能压缩多少个 
		{
			t &= (s >> (j - i));
			Add(res, dfs(i, t) * dfs(n - j, (s >> j)) % mod); 
		}
	}
	return dp[n][s] = res;
}
int main()
{
	string s; cin >> s;
	int n = s.size();
	bint S = 0;
	for (int i = n - 1; i >= 0; i--) S = (S << 1 | (s[i] - '0'));
	write(dfs(n, S));
	return 0;
}

评论

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

正在加载评论...