agc020E Encoding Subsets
Solution
- 暴力递归即可。
- 长度小的时候预处理DP即可。
- 最多递归三层。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 105
#define maxm 14
#define ll long long
#define uint unsigned int
#define mo 998244353
using namespace std;
int n,i,j,k,a[maxm][maxn];
ll f[maxm+1][1<<maxm],g[maxm][maxn];
uint s[maxm][maxn];
void prepare(){
f[0][0]=1;
for(i=1;i<=maxm;i++) for(int S=0;S<1<<i;S++){
f[i][S]=f[i-1][S^(S>>i-1<<i-1)]*((S>>i-1&1)+1)%mo;
for(j=1;j*2<=i;j++){
int T=S>>i-j;
for(k=2*j;k<=i;k+=j){
T&=S>>i-k;
(f[i][S]+=f[i-k][S^(S>>i-k<<i-k)]*f[j][T])%=mo;
}
}
}
}
ll doit(int d){
memset(g[d],0,sizeof(ll)*(a[d][0]+1));
for(int i=1;i<=a[d][0];i++) s[d][i]=s[d][i-1]<<1|a[d][i];
g[d][0]=1;
for(int i=1;i<=a[d][0];i++) {
g[d][i]=g[d][i-1]*(a[d][i]+1)%mo;
for(int j=1;j*2<=i;j++) if (j<=maxm){
int T=s[d][i]^(s[d][i-j]<<j);
for(int k=2*j;k<=i;k+=j){
T&=s[d][i-k+j]^(s[d][i-k]<<j);
(g[d][i]+=g[d][i-k]*f[j][T])%=mo;
}
} else {
a[d+1][0]=j;
for(int k=1;k<=j;k++) a[d+1][k]=a[d][i-j+k];
for(int k=2*j;k<=i;k+=j){
for(int l=1;l<=j;l++) a[d+1][l]&=a[d][i-k+l];
(g[d][i]+=g[d][i-k]*doit(d+1))%=mo;
}
}
}
return g[d][a[d][0]];
}
int main(){
freopen("ceshi.in","r",stdin);
prepare();
char ch=getchar();
while (ch=='0'||ch=='1') a[0][++a[0][0]]=ch-'0',ch=getchar();
if (a[0][0]<=maxm){
k=0;for(i=a[0][0];i>=1;i--) k=(k<<1)|a[0][i];
printf("%lld\n",f[a[0][0]][k]);
return 0;
}
printf("%lld\n",doit(0));
}