• 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;
    }
    
  • 相关阅读:
    WHU 1540 Fibonacci 递推
    CSU 1378 Shipura 简单模拟
    UVALive 6486 Skyscrapers 简单动态规划
    JAVA杂记
    JAVA的main方法
    Java中的System类
    认识理解Java中native方法(本地方法)
    JAVA导入支持类
    从UDP的”连接性”说起–告知你不为人知的UDP
    udp如何实现可靠性传输?
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10970292.html
Copyright © 2020-2023  润新知