CF1546D - AquaMoon and Chess(组合数学)
题目
题解
问题转化:1可以隔着一个1和0交换位置,等价于将两个连续的1看作一个整体,这个“11”可以与相邻的任意元素交换位置。
统计字符串中有多少组“11”(每个1至多属于1组),于是字符串等价于由“11”,“1”,“0”组成。假设“11”个数是n,“0”的个数为m,不同的情况数等价于在m个“0”之间插入n个“11”的方案数。
这个就是经典n个盒子放k个球模型,在该题中,是m+1个盒子,放n个球,盒子可以为空,故方案数为C(n+m, m)。
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 3e5 + 10;
const int M = 998244353;
char s[N];
inline ll qpow(ll a, ll b, ll m) {
ll res = 1;
while(b) {
if(b & 1) res = (res * a) % m;
a = (a * a) % m;
b = b >> 1;
}
return res;
}
ll fact[N], rfact[N];
ll C(int n, int m) {
return fact[n] * rfact[n - m] % M * rfact[m] % M;
}
int main() {
IOS;
fact[0] = rfact[0] = 1;
for(int i = 1; i < N; i++) {
fact[i] = fact[i - 1] * i % M;
rfact[i] = rfact[i - 1] * qpow(i, M - 2, M) % M;
}
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
cin >> s;
int a = 0, b = 0;
for(int i = 0; s[i]; i++) {
if(s[i] == '1') {
if(i + 1 < n && s[i + 1] == '1') {
a++;
i++;
}
} else {
b++;
}
}
cout << C(a + b, b) << endl;
}
}