1546 #732 (Div. 2) D. AquaMoon and Chess(组合数,规律)

LINK

考虑序列中一定是一段 0 0 0,然后一段 1 1 1,然后一段 0 0 0

考虑单独拿出一段 1 1 1来观察它的移动

00111100 00111100 00111100

可以发现,一开始只能从第二个 1 1 1或者倒数第 2 2 2 1 1 1往外面置换,于是可以得到

01101100 01101100 01101100或者 00110110 00110110 00110110

如果你想,现在你可以让 11 11 11以任意的方式排列

不为什么!!只因为它们是 11 11 11的形式,和 0 0 0置换后还是 11 11 11,所以可以一直往左或往右

然而当这段 1 1 1为奇数时,会留下一个 1 1 1,这个 1 1 1是不成组的,无法自由移动

最后这个单独的 1 1 1的位置取决于其他成组 11 11 11的移动

所以设序列中有 x x x 11 11 11, y y y 0 0 0

相当于 x + y x+y x+y个元素,其中 x x x个是 11 11 11,任意排列( 1 1 1是无所谓的, 11 11 11的排列决定了剩余 1 1 1的位置)

答案是 ( x + y x ) \binom{x+y}{x} (xx+y)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
const int maxn = 3e5+10;
int n,f[109][109],fac[maxn];
char a[maxn];
int quick(int x,int n)
{
	int ans = 1;
	for( ; n ; n>>=1,x=x*x%mod )
		if( n&1 )	ans = ans*x%mod;
	return ans;
}
int C(int n,int m)
{
	if( m>n )	return 0ll;
	return fac[n]*quick( fac[m]*fac[n-m]%mod,mod-2 )%mod;
}
signed main()
{
	fac[0] = 1;
	for(int i=1;i<=200000;i++)	fac[i] = 1ll*fac[i-1]*i%mod;
	int t; cin >> t;
	while( t-- )
	{
		cin >> n >> ( a+1 );
		int x = 0, y = 0, zi = 0;
		a[n+1] = '0';
		for(int i=1;i<=n;i++)
		{
			if( a[i]=='1' )	zi++;
			else	
			{
				y++; x += zi/2;
				zi = 0;
			}
		}
		x += zi/2;
		cout << C( x+y,x ) << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值