CF EDU 120 D - Shuffle
D - Shuffle
组合数学
记当前枚举的区间从第 i 个 1 到 第 i + k - 1 个 1,记 j = i + k - 1, 那这些 1 可以随意排列的区间为 , 设为 , 这个区间对答案的贡献为
但是和上一个区间会有重复,重复的数量为
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 5e3 + 10;
const int mod = 998244353;
int n, k;
int pos[N], cnt;
ll fac[N], finv[N];
ll qmi(ll a, ll b)
{
ll ans = 1;
while(b)
{
if (b & 1)
ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans % mod;
}
void presolve()
{
fac[0] = finv[0] = 1;
for (int i = 1; i <= N - 5; i++)
{
fac[i] = fac[i-1] * i % mod;
finv[i] = qmi(fac[i], mod - 2);
}
}
ll C(int n, int m)
{
if (m < 0 || n - m < 0)
return 0;
return fac[n] * finv[m] % mod * finv[n-m] % mod;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
presolve();
cin >> n >> k;
string s;
cin >> s;
s = " " + s;
for (int i = 1; i <= n; i++)
if (s[i] == '1')
pos[++cnt] = i;
if (k == 0 || cnt < k)
{
cout << 1 << endl;
return 0;
}
ll ans = 0;
pos[cnt+1] = n + 1;
for (int i = 1; i + k - 1 <= cnt; i++)
{
int j = i + k - 1;
int l = pos[i-1] + 1;
int r = pos[j+1] - 1;
// cout << l << " " << r << endl;
ans = (ans + C(r - l + 1, k)) % mod;
if (i > 1)
ans = (ans - C(pos[j] - pos[i-1] - 1, k - 1)) % mod;
}
cout << (ans + mod) % mod << endl;
return 0;
}
分类:
acm / 组合数学
标签:
组合数学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!