原题链接:Problem - 1622D - Codeforces
题目大意:给你一串01串,告诉你长度n和一个数k,这个串中所有1的数量为k的子串,可以把这段子串重新排序。问你最后这个串能有多少种。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))
const ll M = 998244353;
const int N = 5010;
char s[N];
int a[N], pre[N];
ll fac[N], invfac[N];
inline ll qpow(ll a, ll n, ll p)// 快速幂
{
ll ans = 1;
while (n)
{
if (n & 1)
ans = ans % p * a % p;
a = a % p * a % p;
n >>= 1;
}
return ans;
}
inline ll inv(ll a, ll p)
{
return qpow(a, p - 2, p);
}
void init() //注意要在主函数中init()!!!
{
fac[0] = 1;
for (int i = 1; i < N; ++i) fac[i] = (fac[i - 1] * i) % M;
invfac[N - 1] = inv(fac[N - 1], M);
for (int i = N - 2; i >= 0; --i) invfac[i] = (invfac[i + 1] * (i + 1)) % M;
}
ll C(int n, int m)
{
if (n < m || m < 0) return 0;
return fac[n] * invfac[m] % M * invfac[n - m] % M;
}
int main()
{
init();
int n, k;
scanf("%d %d", &n, &k);
scanf("%s", s + 1);
rep(i, n) a[i] = s[i] - '0';
rep(i, n) pre[i] = pre[i - 1] + a[i];
ll ans = 1;
if(pre[n] < k){puts("1"); return 0;}
rep(i, n)
for(int j = i + 1; j <= n; j++){
if(pre[j] - pre[i - 1] > k) break;
int cnt = pre[j] - pre[i - 1];
cnt -= (a[i] == 0) + (a[j] == 0);
ans = (ans + C(j - i - 1, cnt)) % M;
}
printf("%lld", ans);
return 0;
}