题意:
假设有 0 到 n-1种数字,随机选取(可以重复),得到的和为k组合数量有多少种。
题解:
设想一个 n 为3的情况:
m\k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 2 | 3 | 2 | 1 | 0 | 0 | 0 | 0 |
3 | 1 | 3 | 6 | 7 | 6 | 3 | 1 | 0 | 0 |
4 | 1 | 4 | 10 | 16 | 19 | 16 | 10 | 3 | 1 |
设想一个 n 为4的情况:
m\k | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 2 | 3 | 4 | 3 | 2 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 1 | 3 | 6 | 10 | 12 | 12 | 10 | 6 | 3 | 1 | 0 | 0 | 0 |
4 | 1 | 4 | 10 | 20 | 31 | 40 | 44 | 40 | 31 | 20 | 10 | 4 | 1 |
我们可以发现这是一个展开式三角形 (1+x+x^2+x^3...+x^n-1)^m。
推导:
x1+x2+...+xm = k (xi 无上界) 想到了隔离板的问题:
7个球用3个隔离板分开的有多少情况,即 C(6,3);
所以设 Xi = xi+1,得:X1+X2+...+Xm = k + m ,所以在xi < n的情况下有 C(k+m-1,m-1) 种情况。
同理 x1+x2+...+xm = k (xi < n),则令 Xi = x1+1-n 得:X1+X2+...+Xm = k + m - c*n(c 为xi超过n的个数);
所以有C(k+m-c*n-1, m-1)种情况,但是c的个数和位置是不一样的,所以要乘以C(m,c)。
因为容斥,所以可以得到公式:
比赛的时候很惨,疯狂WA,赛后发现在求和的过程中没有 +mod 导致答案会有出入,心好累。
AC代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define mem(a) memset(a, 0, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int maxn = 2e5+10;
ll fac[maxn], inv[maxn], ans[maxn];
ll temp;
ll getpow(ll a, int b){
ll sum = 1;
while(b){
if(b & 1){
sum = (sum * a) % mod;
}
a = (a*a) % mod;
b >>= 1;
}
return sum;
}
ll C(int n, int m){
return fac[n]*inv[m]%mod * inv[n-m]%mod;
}
void init(){
temp = getpow(2, mod-2);
fac[0] = inv[0] = 1;
for(int i = 1; i < maxn; i++){
fac[i] = (i*fac[i-1]) % mod;
inv[i] = getpow(fac[i], mod-2);
}
}
int main(){
int t;
init();
scanf("%d", &t);
while(t--){
ll n, m, k;
scanf("%lld %lld %lld", &n, &m, &k);
ll sum = 0;
for(ll r = 0; r <= k/n; r++){
if(r%2){
sum = (sum+mod-C(m, r)*C(k-n*r+m-1, m-1) % mod) % mod;
}
else{
sum = (sum+mod+C(m, r)*C(k-n*r+m-1, m-1) % mod) % mod;
}
}
printf("%lld\n", sum % mod);
}
}