Codeforces Round #732 (Div. 2) D. AquaMoon and Chess

首先我们来考虑比较简单的情况
1100000000000 1100000000000 1100000000000
11 11 11看做一个团,这个团可以在数轴上移动,每一种团的情况对应一种 s t a t e state state
推广,对于一个奇数长度的连续串
000011111000000 000011111000000 000011111000000
可以知道里面有 l e n / 2 len/2 len/2个团,当这个连续串左右团的数量确定的时候这个团留下的“1”位置唯一确定,比如上面的例子,可以知道如果两个团在左边那么留下的就是最右边的 1 1 1,一个在左边一个在右边留下的就是中间的 1 1 1……

回过来看题目,我们找出一个字符串里所有的团,然后由上面得到的结论,当团的位置确定留下的单独的“1”位置确定,所以只需要考虑团的位置关系。
问题转化成 1 ∗ m 1*m 1m的空间放 n n n 1 ∗ 2 1*2 12物品的方案数量。写个公式就完了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=998244353;
ll poww(ll a,ll b)
{
    ll t=1;
    while(b>1)
    {
        if(b%2==1)t=t*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return t*a%mod;
}
ll poww1[100005],poww2[100005];
void init()
{
    poww1[0]=1;
    poww2[0]=1;
    for(int i=1;i<=100000;i++)poww1[i]=poww1[i-1]*i%mod;
    for(int i=1;i<=100000;i++)poww2[i]=poww2[i-1]*poww(i,mod-2)%mod;
//    printf("%lld\n",poww2[3]);

}
char s[100005];
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        scanf("%s",s+1);
        int cnt0=0,cnt=0,cnt2=0;

        for(int i=1;i<=n;i++)
        {
            if(s[i]=='0')cnt0++;
            if(s[i]=='1')cnt++;
            if(s[i]=='0')
            {
                cnt2+=cnt/2;
                cnt=0;
            }
        }
        cnt2+=cnt/2;
        printf("%lld\n",poww1[cnt0+cnt2]*poww2[cnt0]%mod*poww2[cnt2]%mod);

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值