题目链接:codeforces 1622D
题解
暴力枚举区间 ,每次考虑把边界上的 放在中间的方案数。用预处理的方法求组合数。
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <iostream> #include <vector> #include <string> using namespace std; typedef long long ll; const int N =5000+10; const int mod = 998244353; ll n, k; string s; ll fac[N], inv_fac[N]; ll a[N]; ll qpow(ll a, ll b) { ll res = 1; a %= mod; while (b > 0) { if (b & 1) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; } ll inv(ll x, ll p) { return qpow(x, p-2); } void prework() { fac[0] = inv_fac[0] = 1; for (int i = 1; i <= 5000; i++) { fac[i] = fac[i-1] * i % mod; inv_fac[i] = inv_fac[i-1] * inv(i, mod) % mod; } } ll C(ll n, ll m) { if (n < m || m < 0) return 0; return fac[n] * inv_fac[m] % mod * inv_fac[n-m] % mod; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> k >> s; prework(); for (int i = 0; i < n; i++) a[i] = s[i] - '0'; vector<int> pre(n+1); for (int i = 0; i < n; i++) { pre[i+1] = pre[i] + a[i]; } ll ans = 1; if (pre[n] >= k) { for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int cnt = pre[j+1] - pre[i]; if (cnt <= k) { cnt -= (a[i] ^ 1) + (a[j] ^ 1); int len = j - i - 1; ans += C(len, cnt); ans %= mod; } } } } cout << ans << endl; return 0; }
|


yngcy
夕拾天星,曦携明露
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。