agc020 E Encoding Subsets (dp)

题意

链接
给你一个01串A,你可以使用(P*K)这样的方式来表示PPPP...P(k个P且k>1),允许嵌套。问满足 A a n d B = B A and B = B 的B其表示方法数之和。两种表示方法不同当且仅当所对应的字符串不同。
n<=100

思路

  • 首先思考如何求一个确切的A的表示方法数。
  • 使用区间dp,开头要么没有括号,要么枚举第一个括号的长度与K.
  • 类似地,我们设f(S)表示S的子集的所有方法数之和。仅有几点不同:
  • 若s[1]=1,则第一个位置可以是0也可以是1.
  • 枚举第一个括号的长度时,要将对应位置and起来求f。
  • 加上记忆化即可通过本题,题解宣称时间复杂度 O ( n 3 ) O(n^3)
  • 复杂度分析?不存在的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo = 998244353;
const int N = 105;
string init;
int n;
unordered_map<string, int> f;

ll fet(string a) {
	if (a.size() == 0) return 1;
	if (a.size() == 1) return 1 + a[0] - '0';
	if (f.count(a)) return f[a];
	ll ret = 0;
	ret = (1 + a[0] - '0') * fet(string(a.begin() + 1, a.end()));
	for(int p = 1; p * 2 <= a.length(); p++) {
		string nx = string(p, '1');
		for(int i = p - 1; i < a.length(); i += p) {
			for(int j = i - p + 1, cs = 0; j <= i; j++, cs++) {
				nx[cs] = ((nx[cs] - '0') & (a[j] - '0')) + '0';
			}
			if (i > p - 1)
				ret = (ret + fet(nx) * fet(string(a.begin() + i + 1, a.end()))) % mo;;
		}
	}
	return f[a] = ret % mo;
}

int main() {
	freopen("e.in","r",stdin);
	cin >> init;
	cout << fet(init) << endl;
}

发布了266 篇原创文章 · 获赞 93 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/jokerwyt/article/details/102744213