组合+容斥

/*
HDU 6397 A: Character Encoding 组合计数+容斥
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6397
题意:n m k  选择区间[0,n-1]的数字,每个数字可以选择最多不超过m个使得他们的和等于k;
组合计数+容斥原理 经典的球盒问题
由于和为k,不妨先进行设置每一份的大小为多少,然后对剩下的部分直接进行计算,那么再不存在
n的限制时,答案即为C(k+m-1,m-1);
由于存在限制条件,只能选0~n-1的数
如果只有c个,那么这个数x’>=n一定成立。现在我们做这样一个操作,将所有大于等于n的x全部减去n,这样问题由原来的x 1 + x 2 + . . . x m = k x_1+x_2+...x_m=kx 
1
​    
 +x 
2
​    
 +...x 
m
​    
 =k转换成了x1+x2+x3+.....+xm
 =k−n∗c原来的x1…xm可能是大于等于n的,但是转化以后的x’全部是小于n的而且大于0,这个就相当于转换成了上述没有限制的一个子问题。就可以用上面说的方法求数量     
*/
#include<bits/stdc++.h>
using namespace std;

#define e exp(1)
#define pi acos(-1)
#define mod 998244353
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a))
int gcd(int a,int b){return b?gcd(b,a%b):a;}

const int maxn=2e5+5;
ll n,m,k;
ll f[maxn],inv[maxn];
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans%mod;
}
void init()
{
    f[0]=inv[0]=1;
    for(int i=1; i<maxn; i++)
    {
        f[i]=f[i-1]*i%mod;
        inv[i]=qpow(f[i],mod-2);
    }
}

ll C(ll n,ll m)
{
    return f[n]*inv[n-m]%mod*inv[m]%mod;
}
int main()
{
    init();
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&n,&m,&k);
        ll ans=C(k+m-1,m-1);
        ll len=min(k/n,m);
        for(int i=1; i<=len; i++)
        {
            if(i&1)ans=(ans-C(m,i)*C(k+m-1-i*n,m-1)%mod+mod)%mod;
            else ans=(ans+C(m,i)*C(k+m-1-i*n,m-1)%mod)%mod;
        }
        printf("%lld\n",ans%mod);
    }
    return 0;
}