题意:问有多少种不重复的m个数,值在[0,n-1]范围内且和为k。
分析:当k<=n-1时,肯定不会有盒子超过n,结果是C(m+k-1,k);当k>m*(n-1)时,结果是0。
剩下的情况,可以转化为组合数学中的放球问题,球与球之间没有区别,盒子之间有区别且每个盒子不超过n-1个球。
根据容斥原理得,结果为signma((-1)^i * C(m,i) * C(m+k-i*p-1, k-i*n))
#include<bits/stdc++.h> using namespace std; const int mod = 998244353; const int maxn = 2e5+5; typedef long long LL; LL fac[maxn],inv[maxn]; LL res[maxn]; LL qpow(LL b,int n){ LL res=1; while(n){ if(n&1) res=res*b%mod; b = b*b%mod; n>>=1; } return res; } void pre() { fac[0]=fac[1]=1; for(int i=2;i<maxn;++i) fac[i]=i*fac[i-1]%mod; inv[maxn-1]=qpow(fac[maxn-1],mod-2); for(int i=maxn-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; } LL Comb(int n,int k) { if(n==k) return 1; else if(n<k) return 0; return fac[n]*inv[k]%mod *inv[n-k]%mod; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif pre(); int T; scanf("%d",&T); while(T--){ int N,M,k; scanf("%d%d%d",&N,&M,&k); if(k<=N-1) printf("%lld ",Comb(M+k-1,k)); else if(k>M*(N-1)) printf("0 "); else{ LL res=0; for(int i=0;i<=k/N;++i){ if(i&1) res = (res+mod-Comb(M,i)*Comb(M+k-1-i*N,k-i*N)%mod)%mod; else res = (res+Comb(M,i)*Comb(M+k-1-i*N,k-i*N)%mod)%mod; } printf("%lld ",res); } } return 0; }