《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}$
这里需要预处理阶乘的逆元,不然时间复杂度不够。
// 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;
}
View Code

 

posted @ 2021-05-25 19:13  levill  阅读(53)  评论(0编辑  收藏  举报