HDU6397 Character Encoding
Problem - 6397 Character Encoding
题意:给定 \(n,m,k\) 问有多少种方案使得 \(\sum_{i=1}^m x_i = k(0 \le x_i \lt n)\)
知识点:容斥
先考虑无 \(n\) 限制的情况,问题等价与 \(\sum_{i=1}^m x_i = k + m(1 \le x_i)\)
这个可以隔板法得出 \(m+k-1 \choose m-1\)
再考虑容斥,设至少有 \(i\) 个 \(x\) 是大于 \(n\) 的方案为 \(f_i\) 则有
\[f_i = {m \choose i} * {m + k - i * n - 1 \choose m - 1}
\]
意思是先对 \(i\) 个 \(x\) 分配 \(n\) 然后按照隔板法求
最后容斥即可
答案为
\[ans = \sum_{i=0}^m (-1)^i * f_i
\]
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 3e5 + 10;
const int MOD = 998244353;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
LL f1[N], f2[N];
LL q_pow(LL a, LL b, LL p) {
LL res = 1;
for (; b; b >>= 1) {
if (b & 1) res = res * a % p;
a = a * a % p;
}
return res;
}
LL C(LL n, LL m) {
if (n < m) return 0;
if (n < 0 || m < 0) return 0;
if (n == m) return 1;
return f1[n] * f2[m] % MOD * f2[n - m] % MOD;
}
inline void solve() {
LL n, m, k; cin >> n >> m >> k;
LL res = 0;
int ops = 1;
for (LL i = 0; i <= m; i ++ ) {
res = (res + 1ll * ops * C(m, i) * C(m + k - 1 - i * n, m - 1) % MOD + MOD) % MOD;
ops *= -1;
}
cout << res << endl;
}
signed main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int n = 300000;
f1[0] = 1;
for (int i = 1; i <= n; i ++ ) f1[i] = f1[i - 1] * i % MOD;
f2[n] = q_pow(f1[n], MOD - 2, MOD);
for (int i = n; i; i -- ) f2[i - 1] = f2[i] * i % MOD;
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}