CF1750F Majority 题解
记 $f_i$ 表示长度为 $i$ 的答案,发现不好直接求,考虑用 $2^{i-2}$ 减去两端点为 $1$ 且不合法的串的个数。
考虑一个不合法的串做完全部操作以后长什么样,发现不合法当且仅当对于任意两个全为 $1$ 且中间全为 $0$ 的连续段,长度和小于中间的 $0$ 的个数。
考虑让两段 $1$ 再往中间取同一长度的一段:

然后直接 dp 计数即可,时间复杂度 $\mathcal O(n^2)$。
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define mxn 5003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
int n,md;
ll f[mxn],d[mxn],dp[mxn],d1[mxn];
signed main(){
cin>>n>>md;
d[0]=1;
rep(i,1,n)d[i]=d[i-1]*2%md;
f[1]=1;
rep(i,2,n){
if(!(i&1))dp[i]=f[i>>1];
rept(j,1,i){
if(i-j*3-1<0)break;
dp[i]=(dp[i]+d1[i-j*3-1]*f[j])%md;
}
d1[i]=(d1[i-1]+dp[i])%md;
f[i]=d[i-2];
rept(j,1,i){
if(i-j*2-1<0)break;
f[i]=(f[i]-d1[i-j*2-1]*f[j])%md;
}
}
cout<<(f[n]+md)%md;
return 0;
}

浙公网安备 33010602011771号