暴力枚举区间 [l, r],每次考虑把边界上的 1 1 1 放在中间的方案数。用预处理的方法求组合数。
参考代码:#include#include #include 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 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; }



