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 AandB=B的B其表示方法数之和。两种表示方法不同当且仅当所对应的字符串不同。
n<=100

思路

  • 首先思考如何求一个确切的A的表示方法数。
  • 使用区间dp,开头要么没有括号,要么枚举第一个括号的长度与K.
  • 类似地,我们设f(S)表示S的子集的所有方法数之和。仅有几点不同:
  • 若s[1]=1,则第一个位置可以是0也可以是1.
  • 枚举第一个括号的长度时,要将对应位置and起来求f。
  • 加上记忆化即可通过本题,题解宣称时间复杂度 O ( n 3 ) O(n^3) O(n3)
  • 复杂度分析?不存在的
#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值