组合数学 + 容斥原理
先不考虑限制条件,朴素的求m个数之和等于k可以用公式直接得出。
考虑上限制条件,我们可以分成1...k/n个数>=n的情况,但是不能直接相减。
因为后面那种情况一定包含前面小的情况,这里我们可以考虑容斥原理。
先分析只有一个数>=n的情况,我们假定某个数>=n,但是其他数的大小我们是无法确定的,当另外一个数也>=n的时候,我们每次考虑其中一个数>=n时,都把另一个数>=n的情况也减去了,所以在考虑两个数>=n的时候我们要把多减的加回来。
再后面也是同理,对于奇数的情况我们减,偶数的情况加,最后就能得到答案。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int X = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
return w ? -X : X;
}
inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
}
const int N = 200005;
const int p = 998244353;
int _, n, m, k;
ll inv[N], f[N];
void calc(){
inv[1] = 1, f[1] = 1, f[0] = 1, inv[0] = 1;
for(int i = 2; i <= N; i ++){
f[i] = (f[i - 1] * i) % p;
}
for(int i = 2; i <= N; i ++){
inv[i] = (p - p / i) * inv[p % i] % p;
}
for(int i = 2; i <= N; i ++){
inv[i] = (inv[i] % p * inv[i - 1] % p) % p;
}
}
ll C(int n, int m){
if(n < m) return 0;
return (f[n] * inv[m] % p * inv[n - m] % p) % p;
}
int main(){
calc();
for(_ = read(); _; _ --){
n = read(), m = read(), k = read();
ll ans = C(k + m - 1, m - 1);
for(int i = 1; i * n <= k; i ++){
if(i & 1){
ans = ((ans - (C(m, i) * C(k - i * n + m - 1, m - 1)) % p) + p) % p;
}
else{
ans = (ans + (C(m, i) * C(k - i * n + m - 1, m - 1)) % p) % p;
}
}
printf("%lld
", ans);
}
return 0;
}