CF1608D Dominoes (2400) (组合数学)
https://codeforces.com/contest/1608/problem/D
- B,W 都要出现n次。
- 如果出现BB或WW的话,一定可以通过调整站位摆出合法情况。
- 如果没有BB或WW的话,画一下例子我们发现,所有牌必须是相同的涂色:都是BW或都是WB,否则一定矛盾。
- \(ans = \binom{2 * n - cntW - cntB}{n - cntW} - cal\) cal是有且只有BW,WB的情况数。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
typedef long long ll;
const int N = 2e5 + 5;
const int mod = 998244353;
char ss[N][3];
ll F[N], inv[N];
ll qmi(ll m, ll k) {
ll res = 1 % mod;
while (k){
if(k & 1) res = res * m % mod;
m = m * m % mod;
k >>= 1;
}
return res;
}
void init() {
int n = 200000;
F[0] = inv[0] = 1;
for(int i = 1; i <= n; ++ i) F[i] = F[i - 1] * i % mod;
inv[n] = qmi(F[n], mod - 2);
for(int i = n - 1; i >= 1; -- i) inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(ll n, ll m) {
return F[n] * inv[m] % mod * inv[n - m] % mod;
}
int main() {
init();
ll n; scanf("%lld", &n);
ll cntW = 0, cntB = 0;
for (int i = 1; i <= n; ++ i) {
scanf(" %s", ss[i]);
if(ss[i][0] == 'W') ++ cntW; if(ss[i][1] == 'W') ++ cntW;
if(ss[i][0] == 'B') ++ cntB; if(ss[i][1] == 'B') ++ cntB;
}
if (cntW > n || cntB > n) {
cout << 0 << '\n'; return 0;
}
ll ans = C(2 * n - cntB - cntW, n - cntB);
ll cal = 1;
int ok1 = 1, ok2 = 1; //能否达成全BW,全WB
for (int i = 1; i <= n; ++ i) {
if(ss[i][0] == '?' && ss[i][1] =='?') cal = cal * 2 % mod;
if(ss[i][0] == ss[i][1] && ss[i][0] != '?') { //出现WW,BB就不用再减了
cal = 0; ok1 = ok2 = 0;
}
if(ss[i][0] == 'B' || ss[i][1] =='W') ok1 = 0; if(ss[i][0] == 'W' || ss[i][1] == 'B') ok2 = 0;
}
ans = ((ans - cal + mod) % mod + ok1 + ok2) % mod;
cout << ans << '\n';
return 0;
}