AGC020E Encoding Subsets

AGC020E Encoding Subsets

设答案为 f(s)f(s)ss 为原串。

决策最后一位字符 cc 参不参与压缩。

cc 不参与压缩,方案数为:

f(s){f(sc)c=0f(sc)×2c=1f(s)\leftarrow\begin{cases}f(s-c) & c='0'\\f(s-c)\times 2 & c='1'\end{cases}

cc 参与压缩时,暴力枚举 cc 所在压缩的最后一段。

设从末尾开始的压缩串为 tt,压缩成了 kk 个,则这一段串可以记作 t×kt\times k,方案数为 f(s)f(t)×f(st×k)f(s)\leftarrow f(t)×f(s−t×k),注意这里并不需要管当前是否可以压缩,取 kk 个压缩串的交集递归下去就行了,有点巧妙。

状态数较少,考虑记忆化搜索,可过。

#include <bits/stdc++.h>

using namespace std;

#define int long long
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')

inline int read()
{
	int x = 0, f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-')
			f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		x = x * 10 + c - '0', c = getchar();
	return x * f;
}

inline void write(__int128 x)
{
	if (x < 0)
	{
		putchar('-');
		x = -x;
	}
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}

const int mod = 998244353;

string s;

__int128 S;

map<__int128, int> mp[110];

int dfs(int l, __int128 s)
{
	if(!l) return 1;
	if(mp[l].count(s)) return mp[l][s];
	int res = dfs(l - 1, s >> 1) * ((s & 1) + 1) % mod;
	__int128 a = 0, b = 0;
	for(int i = 1; i <= l; ++i)
	{
		a = (a << 1) | 1, b = s & a;
		for(int j = i + i; j <= l; j += i)
			res = (res + dfs(i, b &= s >> (j - i)) * dfs(l - j, s >> j) % mod) % mod;
	}
	mp[l][s] = res;
	return res;
}

signed main()
{
	cin >> s;
	int l = s.size();
	for(int i = l - 1; i >= 0; --i)
		S = (S << 1) | (s[i] == '1');
	write(dfs(l, S));
	return 0;
}
posted @ 2022-08-01 21:27  蒟蒻orz  阅读(1)  评论(0编辑  收藏  举报  来源