2018 Multi-University Training Contest 8

组合数学 + 容斥原理

先不考虑限制条件,朴素的求m个数之和等于k可以用公式直接得出。

考虑上限制条件,我们可以分成1...k/n个数>=n的情况,但是不能直接相减。

因为后面那种情况一定包含前面小的情况,这里我们可以考虑容斥原理。

先分析只有一个数>=n的情况,我们假定某个数>=n,但是其他数的大小我们是无法确定的,当另外一个数也>=n的时候,我们每次考虑其中一个数>=n时,都把另一个数>=n的情况也减去了,所以在考虑两个数>=n的时候我们要把多减的加回来。

再后面也是同理,对于奇数的情况我们减,偶数的情况加,最后就能得到答案。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
    int X = 0, w = 0; char ch = 0;
    while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
    A ans = 1;
    for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
    return ans;
}

const int N = 200005;
const int p = 998244353;
int _, n, m, k;
ll inv[N], f[N];

void calc(){
    inv[1] = 1, f[1] = 1, f[0] = 1, inv[0] = 1;
    for(int i = 2; i <= N; i ++){
        f[i] = (f[i - 1] * i) % p;
    }
    for(int i = 2; i <= N; i ++){
        inv[i] = (p - p / i) * inv[p % i] % p;
    }
    for(int i = 2; i <= N; i ++){
        inv[i] = (inv[i] % p * inv[i - 1] % p) % p;
    }
}

ll C(int n, int m){
    if(n < m) return 0;
    return (f[n] * inv[m] % p * inv[n - m] % p) % p;
}

int main(){

    calc();
    for(_ = read(); _; _ --){
        n = read(), m = read(), k = read();
        ll ans = C(k + m - 1, m - 1);
        for(int i = 1; i * n <= k; i ++){
            if(i & 1){
                ans = ((ans - (C(m, i) * C(k - i * n + m - 1, m - 1)) % p) + p) % p;
            }
            else{
                ans = (ans + (C(m, i) * C(k - i * n + m - 1, m - 1)) % p) % p;
            }
        }
        printf("%lld
", ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/onionQAQ/p/10970292.html