#codeforces 1546D - AquaMoon and Chess 題解
阿新 • • 發佈:2021-07-12
原題連結``
思路:
顯然如果有連續偶數個“1”,那麼這些一可以拆成若干組“11”自由移動。
因此有了思考方向,用捆綁法,以2個“1”一組。
那麼,如果有連續奇數個“1”該怎麼辦?
經過操作觀察,我們發現,多出來的“1”我們其不需要理它,去掉一個“1”將剩下的偶數個“1”按上述分組,將這些組和0排列後,原來多處來的一個“1”是唯一確定的
因此。我們記錄0的個數cnt0,記錄組數g
答案為從cnt0 + g 個數中 取出g個數的方案數
程式碼:
#include <bits/stdc++.h> using namespace std; #define ll long long const ll mod = 998244353; ll t; ll n; ll cnt0; ll cnt1; ll g; ll ans; string s; ll f[100010]; ll fin[100010]; ll qpow(ll x, ll y) { ll ret = 1ll; while (y) { if (y & 1) ret = (ret * x) % mod; x = (x * x) % mod; y >>= 1; } return ret % mod; } ll inv(ll x) { return qpow(x, mod - 2); } void init() { f[0] = fin[0] = 1ll; for (ll i = 1; i <= 100000; i++) { f[i] = (i * f[i - 1]) % mod; fin[i] = (fin[i - 1] * inv(i)) % mod; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); init(); cin >> t; while (t--) { cnt0 = cnt1 = g = 0; cin >> n; cin >> s; for (int i = 0; i < s.length(); i++) { if (s[i] == '1') { if (i == s.length() - 1) { cnt1 ++; g += cnt1 / 2; } else { cnt1 ++; } } else { cnt0 ++; g += cnt1 / 2; cnt1 = 0; } } ans = ((f[cnt0 + g] * fin[g]) % mod * fin[cnt0]) % mod; cout << ans << "\n"; } return 0; }