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;
}
posted @ 2024-01-31 13:21  zifanwang  阅读(22)  评论(0)    收藏  举报  来源