首先我们来考虑比较简单的情况
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
1∗m的空间放
n
n
n个
1
∗
2
1*2
1∗2物品的方案数量。写个公式就完了。
#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;
}