题意
链接
给你一个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;
}