加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

模板 - 组合数学 - (新)

发布时间:2020-12-14 04:33:47 所属栏目:大数据 来源:网络整理
导读:全部模板合集的名空间版本,相关知识点应在《组合数学》中寻找,而不是在模板中寻找。 #includebits/stdc++.husing namespace std;typedef long long ll;namespace combinatorics{ //注意需要init(),必要时修改常量 const ll MOD=1e9+7; const int MAXN=2000

全部模板合集的名空间版本,相关知识点应在《组合数学》中寻找,而不是在模板中寻找。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;


namespace combinatorics{
    //注意需要init(),必要时修改常量

    const ll MOD=1e9+7;
    const int MAXN=2000000;

    ll inv[MAXN+5],fac[MAXN+5],invfac[MAXN+5];

    //1. 快速幂 x^n%p
    inline ll qpow(ll x,ll n,ll mod=MOD) {
        ll res=1%mod;
        while(n) {
            if(n&1)
                res=res*x%mod;
            x=x*x%mod;
            n>>=1;
        }
        return res;
    }

    //2. 快速乘 a*b%p 防止乘法溢出ll
    inline ll qmut(ll a,ll b,ll mod=MOD) {
        ll res=0;
        while(b) {
            if(b&1)
                res=(res+a)%mod;
            a=(a+a)%mod;
            b>>=1;
        }
        return res;
    }

    //3. 乘法逆元 快速幂+费马小定理 模必须是质数 (依赖1. 快速幂)
    inline ll inv_p(ll n,ll p=MOD) {
        return qpow(n,p-2);
    }

    //4. 扩展欧几里得算法:返回 g=gcd(a,b) ,以及对应的等式 ax+by=g 的解
    ll exgcd(ll a,ll &x,ll &y) {
        if(!a&&!b)
            return -1;
        if(!b) {
            x=1,y=0;
            return a;
        }
        ll d=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }

    //5. 扩展欧几里得算法求逆元,只要求 a,m 互质
    inline ll inv_rp(ll a,ll mod=MOD) {
        ll x,y;
        ll d=exgcd(a,mod,x,y);
        if(d==1)
            return (x%mod+mod)%mod;
        return -1;
    }

    //6. 线性求乘法逆元
    void init_inv(int n=MAXN,ll mod=MOD) {
        inv[1]=1;
        for(int i=2; i<=n; i++) {
            inv[i]=inv[mod%i]*(mod-mod/i)%mod;
        }
    }

    //7. 线性求阶乘,阶乘乘法逆元 (依赖6. 线性求乘法逆元)
    void init_fac_invfac(int n=MAXN,ll mod=MOD) {
        init_inv(n);
        fac[0]=1,invfac[0]=1;
        for(int i=1; i<=n; i++) {
            fac[i]=fac[i-1]*i%mod;
            invfac[i]=invfac[i-1]*inv[i]%mod;
        }
    }

    //8. 利用阶乘和阶乘逆元计算排列数A_n^m (依赖7. 线性求阶乘,阶乘乘法逆元)
    inline ll A(ll n,ll m,ll mod=MOD) {
        return fac[n]*invfac[n-m]%mod;
    }

    //9. 直接计算排列数A_n^m
    /*ll A(ll n,ll mod=MOD){
        if(m>n) return 0;
        ll u=1;
        for(int i=n-m+1;i<=n;i++)
            u=u*i%mod;
        return u;
    }*/

    //10. 利用阶乘和阶乘逆元计算组合数C_n^m (依赖7. 线性求阶乘,阶乘乘法逆元)
    inline ll C(ll n,ll mod=MOD) {
        return fac[n]*invfac[n-m]%mod*invfac[m]%mod;
    }

    //11. 直接计算组合数C_n^m
    /*ll C(ll n,ll mod=MOD){
        if(m>n) return 0;
        ll u=1,d=1;
        for(int i=n-m+1;i<=n;i++)
            u=u*i%mod;
        for(int i=1;i<=m;i++)
            d=d*i%mod;
        return u*inv(d)%mod;
    }*/

    //12. 卢卡斯定理计算组合数C_n^m%p,p是质数 (依赖10. /11. 计算组合数)
    inline ll Lucas(ll n,ll p=MOD) {
        if(m>n)
            return 0;
        ll ans=1;
        for(; m; n/=p,m/=p)
            ans=ans*C(n%p,m%p)%p;
        return ans;
    }

};


using namespace combinatorics;
//注意需要init(),必要时修改常量


int main(){
    init_fac_invfac();
    cout<<C(9,8)<<endl;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读