http://acm.hdu.edu.cn/showproblem.php?pid=6397
原问题的本质是问m个元素的多重集S,每一种类型的对象至多出现n-1次的S的k组合的个数是多少?
等价于 x1+x2+...+xm=k 0<xi<=n-1 的解的个数
当xi没有上限(xi<=n-1)时由隔板法得C(k+m-1,m-1)
而有上限时,方法是构造母函数(1+x+....+x^(n-1))^m 答案是x^k的系数
对母函数用等比数列求和再二项式展开加泰勒展开得答案。orz(解法来自知乎,侵删)

#define _CRT_SECURE_NO_WARNINGS #include<cmath> #include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> using namespace std; #define rep(i,t,n) for(int i =(t);i<=(n);++i) #define per(i,n,t) for(int i =(n);i>=(t);--i) #define mmm(a,b) memset(a,b,sizeof(a)) typedef long long ll; const int maxn = 5e5 + 10; const ll mod = 998244353; int n, m, k; ll inv[maxn], f[maxn], fac[maxn]; ll c[maxn]; long long kpow(long long a, long long n) { long long res = 1; while (n > 0) { if (n & 1)res = res * a%mod; a = a * a%mod; n >>= 1; } return res; } void init() { f[0] = 1; f[1] = 2; fac[0] = fac[1] = 1; inv[1] = 1; rep(i, 2, maxn) { fac[i] = fac[i - 1] * (ll)i % mod; inv[i] = kpow(fac[i], mod - 2); } } ll C(int n, int m) { if (n < m) return 0ll; if (m == 0 || n == m) return 1ll; if (n - 1 == m || m == 1) return n; return fac[n] * inv[m] % mod * inv[n - m] % mod; } int main() { int t; cin >> t; init(); while (t--) { cin >> n >> m >> k; mmm(c, 0); ll fl = 1; ll ans = 0; rep(r, 0, k / n) { ans += fl * C(m, r)*C(m + k - n * r - 1, k - n * r) % mod; fl = -fl; if (ans < 0)ans += mod; ans %= mod; } cout << ans << endl; } }