CF1546D - AquaMoon and Chess(组合数学)

题目

source

题解

问题转化: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;
    }
}
posted @ 2021-07-17 09:57  limil  阅读(48)  评论(0编辑  收藏  举报