The 2021 CCPC Weihai Onsite M
Link:https://codeforces.com/gym/103428/problem/M。
知识点:组合数学,容斥
简述
给定整数 \(n, m, k\),求满足如下条件的 01 串的数量:
- 长度为 \(n\)。
- 1 的个数为 \(m\)。
- 最长的连续全 1 段的长度为 \(k\)。
\(0\le n,m,k\le 10^5\)。
2S,256MB。
分析
首先把限制 \(k\) 搞掉,记 \(f(x)\) 为仅允许有长度不大于 \(x\) 的全 1 段的方案数,则限定最长段为 \(k\) 的方案数即为 \(f(k) - f(k-1)\)。
然后考虑如何求 \(f(k)\)。限定串中有 \(m\) 个 1,即有 \(n-m\) 个 0,则构造字符串等价于在 \(n-m\) 个 0 之间和两端共 \(n-m+1\) 个空中填入总共 \(m\) 个 1,每个空可填入 \(0\sim k\) 个 1。这是个经典问题,参考 hdu6397,考虑容斥消去填入上限的限制。
设 \(g(i)\) 表示总共填入了 \(m\) 个 1 且没有填入上限,有至少 \(i\) 个空至少填入了 \(k+1\) 的方案数:
- 显然有 \(0\le i\le \min\left( n - m + 1, \frac{m}{(k + 1)}\right)\)。
- 对于 \(i=0\),即每个空没有填数上限,则直接插板法,方案数为 \({{(n-m+1) + m - 1} \choose {n-m-1 + 1}} = {n\choose {n-m}}\)。
- 对于 \(i>0\),考虑先选出 \(i\) 个空为它们预分配 \(k+1\),然后转化为了 \(i=0\) 的情况,方案数为 \({{n-m+1}\choose i}\times {{n - (k+1)\times i} \choose {n-m}}\)。
则有 \(f(k) = \sum\limits_{i} (-1)^i\times g(i)\),注意特判 \(f(-1) = 0\)。
预处理下阶乘和逆元,总时间复杂度 \(O(n)\) 级别。
代码
//知识点:组合数学,容斥
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
const int kN = 1e5 + 10;
const LL p = 998244353;
//=============================================================
int n, m, k;
LL inv[kN], fac[kN], ifac[kN];
//=============================================================
LL C(LL n_, LL m_) {
if (m_ > n_) return 0;
return fac[n_] * ifac[m_] % p * ifac[n_ - m_] % p;
}
void Init() {
inv[1] = fac[0] = fac[1] = ifac[0] = ifac[1] = 1;
for (int i = 2; i < kN; ++ i) {
inv[i]= 1ll * (p - p / i + p) % p * inv[p % i] % p;
fac[i] = fac[i - 1] * i % p;
ifac[i] = ifac[i - 1] * inv[i] % p;
}
}
LL f(LL k_) {
if (k_ == -1) return 0;
LL ans = 0, f = 1;
for (int i = 0; i <= std::min(n - m + 1ll, m / (k_ + 1)); ++ i, f = -f) {
LL d1 = C(n - m + 1, i), d2 = C(n - (k_ + 1) * i, n - m);
ans = (ans + f * d1 * d2 % p + p) % p;
}
return ans;
}
//=============================================================
int main() {
// freopen("1.txt", "r", stdin);
std::ios::sync_with_stdio(0), std::cin.tie(0);
Init();
std::cin >> n >> m >> k;
std::cout << (f(k) - f(k - 1) + p) % p << "\n";
return 0;
}
作者@Luckyblock,转载请声明出处。