Character Encoding Gym - 102192A 生成函数求带限制的m变量和为n的方案数
Character Encoding Gym - 102192A 生成函数求带限制的m变量和为n的方案数
题意
给定\(n,m,k\)
求\(m\)个数相加和为\(k\)且每个数不超过\(n\)的方案数
\[1 \leq n,m\leq10^5,0\leq k \leq10^5
\]
分析
我们写出题给的生成函数形式,注意到就是求
\[[x^k](x^0+x^1+x^2...x^n)^m
\]
于是
\[(1+x+x^2...+x^n)^m = (\frac{1-x^{n}}{1-x})^m
\]
对于分子可以直接二项式定理展开,对于分母用广义二项式定理
\[(\frac{1}{1-x})^m = \sum_{i=0}\binom{-m}{i}(-1)^ix^i=\sum_{i=0}\frac{-m(-m-1)...(-m-i+1)}{i!}(-1)^ix^i = \sum_{i=0}\frac{(m+i-1)!}{(m-1)!i!}x^i=\sum_{i=0}\binom{m+i-1}{i}x^i
\]
于是枚举分子的每一项,计算分母对应项系数即可
代码
int iv[maxn];
int fac[maxn];
inline int C(int n,int m){
if(n < m) return 0;
return mul(fac[n],mul(iv[m],iv[n - m]));
}
int main(){
fac[0] = iv[0] = 1;
for(int i = 1;i < maxn;i++)
fac[i] = mul(fac[i - 1],i);
iv[maxn - 1] = ksm(fac[maxn - 1]);
for(int i = maxn - 2;i;i--)
iv[i] = mul(iv[i + 1],i + 1);
int T = rd();
while(T--){
int n = rd();
int m = rd();
int k = rd();
int ans = 0;
for(int i = 0;i <= m;i++){
if(i * n > k) break;
int sign1 = i & 1;
int p1 = sign1 ? MOD - C(m,i) : C(m,i);
int j = k - i * n;
if(j < 0) break;
int p2 = C(m + j - 1,j);
add(ans,mul(p1,p2));
}
printf("%d\n",ans);
}
}