「杂题乱刷2」CF1738E Balance Addicts

题目链接

CF1738E Balance Addicts

解题思路

发现我们可以直接枚举左端点 \(L\),那么此时显然右端点 \(R\) 的取值范围也随之确定,那么此时 \(L\) 能往右移当且仅当 \(L + 1<R\)\(a_{L+1} = 0\)\(R\) 能往左移当且仅当 \(L<R - 1\)\(a_{R-1} = 0\)

那么 \(L,R\) 的取值范围确定后,此时会有以下两种情况:

  • \(L,R\) 的取值范围不相交,此时显然枚举分的段数 \(k\) 然后两端组合数部分相乘即可。

  • \(L,R\) 的取值部分相交,此时直接让两个取值范围一定,然后枚举分的段数 \(k\),此时显然 \(k\) 为偶数,依然组合数计算即可。

由于双指针,时间复杂度 \(O(n)\)

参考代码

ll n;
ll a[1000010];
ll L,R;
ll pre[1000010],suf[1000010];
ll ans;
ll l,r;
void solve()
{
    ans=1;
    cin>>n;
    forl(i,1,n)
        cin>>a[i];
    forl(i,1,n)
        pre[i]=pre[i-1]+a[i];
    suf[n+1]=0;
    forr(i,n,1)
        suf[i]=suf[i+1]+a[i];
    R=n;
    forL(L,1,n,L<R)
    {
        while(L<R-1 && suf[R]<pre[L])
            R--;
        if(pre[L]==suf[R])
        {
            l=L,r=R;
            while(L<R-1 && suf[R-1]==pre[L])
                R--;
            while(L+1<R && suf[R]==pre[L+1])
                L++;
            ll S=0;
            if(L==R-1 && pre[L]==suf[L+1])
            {
                forll(k,0,r-l+1,2)
                    S=(S+C(r-l+1,k))%mod;
                ans=(ans*S)%mod;
                continue;
            }
            forl(k,0,min(L-l+1,r-R+1))
                S=(S+C(L-l+1,k)*C(r-R+1,k)%mod)%mod;
            ans=(ans*S)%mod;
        }
    }
    cout<<ans<<endl;
}
posted @ 2025-02-13 23:01  wangmarui  阅读(11)  评论(0)    收藏  举报