CF1608D Dominoes (2400) (組合數學)
阿新 • • 發佈:2022-03-18
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; }