zoukankan      html  css  js  c++  java
  • 组合数学

    组合数学

    方法一:预处理 + 递推

    (C_a^b = C_{a-1}^b + C_{a-1}^{b-1})

    时间复杂度:O((n^2))

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MOD = 1e9 + 7;
    const char nl = '
    ';
    const int N = 2000 + 50;
    
    int c[N][N];
    
    void init(){
        for (int i = 0; i < N; ++i)
            for (int j = 0; j <= i ; ++j)
                if (!j) c[i][j] = 1;
                else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
    }
    
    int main(){
        ios::sync_with_stdio(false);
    //    cin.tie(nullptr);
    
        init();
    
        int a, b;
        while (cin >> a >> b){
            cout << c[a][b] << nl;
        }
        return 0;
    }
    
    

    方法二:预处理 + 快速幂求逆元

    (C_a^b = frac{a!}{b!(a-b)!})

    时间复杂度:O((nlog{n}))

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    
    const int MOD = 1e9 + 7;
    const char nl = '
    ';
    const int N = 1e5 + 50;
    
    int fact[N], infact[N];
    
    int qmi(int a, int k, int p){
        int res = 1;
        while (k){
            if (k & 1) res = (LL)res * a % p;
            a = (LL)a * a % p;
            k >>= 1;
        }
        return res;
    }
    
    int main(){
        ios::sync_with_stdio(false);
    //    cin.tie(nullptr);
    
        fact[0] = infact[0] = 1;
        for (int i = 1; i < N; ++i){
            fact[i] = (LL)fact[i - 1] * i % MOD;
            infact[i] = (LL)infact[i - 1] * qmi(i, MOD - 2, MOD) % MOD;
        }
    
        int a, b;
        while (cin >> a >> b){
            cout << (LL)fact[a] * infact[b] % MOD * infact[a - b] % MOD << nl;
        }
        return 0;
    }
    
    

    方法三:卢卡斯定理

    (C_a^b equiv C_{a mod p}^{b mod p} cdot C_{a/p}^{b/p} pmod {p})

    时间复杂度:O((plog{p}))

    https://www.luogu.com.cn/problem/P3807

    题意:求 (C_a^b mod p)

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    
    const char nl = '
    ';
    const int N = 1e5 + 50;
    
    int p;
    
    int qmi(int a, int k){
        int res = 1;
        while (k){
            if (k & 1) res = (LL)res * a % p;
            a = (LL)a * a % p;
            k >>= 1;
        }
        return res;
    }
    
    int C(int a, int b){
        int res = 1;
        for (int i = 1, j = a; i <= b; ++i, --j){
            res = (LL)res * j % p;
            res = (LL)res * qmi(i, p - 2) % p;
        }
        return res;
    }
    
    int lucas(int a, int b){
        if (a < p && b < p) return C(a, b);
        else return (LL)C(a % p, b % p) * lucas(a / p, b / p) % p;
    }
    
    int main(){
        ios::sync_with_stdio(false);
    //    cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--){
            int a, b;
            cin >> b >> a >> p;
            a = a + b;
            cout << lucas(a, b) << nl;
        }
        return 0;
    }
    
    

    方法四:高精度 + 分解质因数

    (C_a^b = frac{a!}{b!(a-b)!})

    (n!) 里质因子 p 的个数:(lfloor frac{n}{p} floor cdot lfloor frac{n}{p^2} floor cdot ldots cdot lfloor frac{n}{p^k} floor)

    #include <bits/stdc++.h>
    using namespace std;
    
    const char nl = '
    ';
    const int N = 5000 + 50;
    
    int primes[N], tot;
    int sum[N];
    bool st[N];
    
    void get_primes(int n){
        for (int i = 2; i <= n; ++i){
            if (!st[i]) primes[tot++] = i;
            for (int j = 0; primes[j] <= n / i; ++j){
                st[primes[j] * i] = true;
                if (i % primes[j] == 0) break;
            }
        }
    }
    
    int get(int n, int p){
        int res = 0;
        while (n){
            res += n / p;
            n /= p;
        }
        return res;
    }
    
    vector<int> mul(vector<int> A, int b){
        vector<int> C;
        int t = 0;
        for (int i = 0; i < A.size(); ++i){
            t += A[i] * b;
            C.push_back(t % 10);
            t /= 10;
        }
        while (t){
            C.push_back(t % 10);
            t /= 10;
        }
        return C;
    }
    
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int a, b;
        cin >> a >> b;
    
        get_primes(a);
    
        for (int i = 0; i < tot; ++i){
            int p = primes[i];
            sum[i] = get(a, p) - get(b, p) - get(a - b, p);
        }
    
        vector<int> res = {1};
        for (int i = 0; i < tot; ++i)
            for (int j = 0; j < sum[i]; ++j)
                res = mul(res, primes[i]);
    
        for (int i = res.size() - 1; i >= 0; --i) cout << res[i];
        cout << nl;
    
        return 0;
    }
    
    
  • 相关阅读:
    Table的基本操作
    MySQL数据库基本操作
    jmeter中服务器返回的cookies的查看
    jemeter的乱码问题
    cucumber的报告
    Cucumber的依赖
    idea里maven执行插件pom文件依赖设置
    Tomcat和jenkins的安装
    maven配置
    Ajax必知必会
  • 原文地址:https://www.cnblogs.com/xiaoran991/p/14402814.html
Copyright © 2011-2022 走看看