《HDU - 6397》
区间[0,n - 1]选定m个数使得他们的和 = k.(可以重复选择)
考虑隔板法:
将k看成k个1.那么就是在这k个数里面插入m - 1个板子的方案数。
即C(k - 1,m - 1)
为什么k - 1,因为两边不能插,为什么两边不能插了可能导致不是m个数。
然后我们这样插显然不存在值为0的情况,但是选择的值又可以为0。
所以我们采取扩下限的思路。
我们把选定的区间变成[1,n],让[1,n]来代表[0,n - 1]。
也就是说我们插入隔板出来的值是1,就相当与原来区间的0.
那么也可以发现,我们这样的话每个值都固定加了1,所以我们的k也需要加m个1。
即题意转化为,选[1,n] = k + m。
此时:我们考虑选的值可以 > n,即没有限制的情况。
即C(k + m - 1,m - 1)。
但是这里有限制。所以我们要考虑容斥思想去存在值 >= n + 1的情况。
定义f[i] = 有i个数超过n的方案数量。
我们考虑怎么计算这个方案数。
假设我们现在从m份中拿出了1个n,然后这k + m - 1 - n排成非空的m份即C(k + m - 1 - n,m - 1)。
然后我们再随机把这个n加入到某一份中即C(m,1)那么此时加入的那一份必定 > n。
两份也同理。
所以f[i] = C(m,i) * C(k + m - 1 - i * n,m - 1).
但是这里可能存在减去其他f[i]的情况。
所以要用到容斥思想:
对于N个物品都至多N个 > n的组合方案 = (1个球 > n的方案数量) - (2个球 > n的方案数量) + (3个球..) - (4个球..)
可以发现是奇加偶减。但是因为我们是要去减去这个方案数。
所以变成奇减偶加。
所以最后为:$ans = \binom{m - 1}{k + m - 1} * \sum_{1}^{m} \binom{i}{m} * \binom{m - 1}{k + m - 1 - i * n} * (-1)_{}^{i}$
这里需要预处理阶乘的逆元,不然时间复杂度不够。
View Code
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 2e5 + 5; const int M = 1e5 + 5; const LL Mod = 998244353; #define pi acos(-1) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } } using namespace FASTIO; /* 区间[0,n - 1]选定m个数使得他们的和 = k. 考虑隔板法: 将k看成k个1.那么就是在这k个数里面插入m - 1个板子的方案数。 即C(k - 1,m - 1) 为什么k - 1,因为两边不能插,为什么两边不能插了可能导致不是m个数。 然后我们这样插显然不存在值为0的情况,但是选择的值又可以为0。 所以我们采取扩下限的思路。 我们把选定的区间变成[1,n],让[1,n]来代表[0,n - 1]。 也就是说我们插入隔板出来的值是1,就相当与原来区间的0. 那么也可以发现,我们这样的话每个值都固定加了1,所以我们的k也需要加m个1。 即题意转化为,选[1,n] = k + m。 此时:我们考虑选的值可以 > n,即没有限制的情况。 即C(k + m - 1,m - 1)。 但是这里有限制。所以我们要考虑容斥思想去存在值 >= n + 1的情况。 定义f[i] = 有i个数超过n的方案数量。 我们考虑怎么计算这个方案数。 假设我们现在从m份中拿出了1个n,然后这k + m - 1 - n排成非空的m份即C(k + m - 1 - n,m - 1)。 然后我们再随机把这个n加入到某一份中即C(m,1)那么此时加入的那一份必定 > n。 两份也同理。 所以f[i] = C(m,i) * C(k + m - 1 - i * n,m - 1). 但是这里可能存在减去其他f[i]的情况。 所以要用到容斥思想: 对于N个物品都至多N个 > n的组合方案 = (1个球 > n的方案数量) - (2个球 > n的方案数量) + (3个球..) - (4个球..) 可以发现是奇加偶减。但是因为我们是要去减去这个方案数。 所以变成奇减偶加。 */ int n,m,k; LL f[N],inv[N]; LL quick_mi(LL a,LL b) { LL re = 1; while(b) { if(b & 1) re = (re * a) % Mod; b >>= 1; a = (a * a) % Mod; } return re; } void init() { f[0] = 1; for(int i = 1;i < N;++i) f[i] = f[i - 1] * i % Mod; inv[N - 1] = quick_mi(f[N - 1],Mod - 2); for(int i = N - 2;i >= 0;--i) inv[i] = inv[i + 1] * (i + 1) % Mod; } LL C(int n,int m) { return f[n] * inv[m] % Mod * inv[n - m] % Mod; } int main() { init(); int ca;ca = read(); while(ca--) { n = read(),m = read(),k = read(); LL ans = C(k + m - 1,m - 1); LL ma = 1; for(int i = 1;i <= m;++i) { ma *= -1; if(k + m - 1 - i * n < m - 1) break; ans = (ans + ma * C(m,i) % Mod * C(k + m - 1 - i * n,m - 1) % Mod) % Mod; ans = (ans + Mod) % Mod; } printf("%lld\n",ans); } system("pause"); return 0; }