zoukankan      html  css  js  c++  java
  • 数论:卢卡斯定理(求组合数)

    点击查看折叠代码块
    /*
    C(n,m) % p = n!/(m! * (n-m)!) % p = n! % p * inv[m!] % p * inv[(n-m)!] % p
    
    求出1-n的前缀积pre[1]--pre[n] 和 1-n的逆元的前缀积 pre_inv[1]--pre_inv[n]
    则 C(n,m) = pre[n] % p * pre_inv[m] % p * pre_inv[n-m] % p
    
    卢卡斯定理:
    Lucas(n,0) = 1
    Lucas(n,m) % p = Lucas(n/p,m/p) * C(n % p,m % p)
    */
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6+10;
    ll n,m,Mod;
    int T;
    
    ll mypow(ll a,ll b){
        ll inv = 1;
        while( b ){
            if( b&1 )  inv = inv*a%Mod;
            a = a*a%Mod;
            b >>= 1;
        }
        return inv;
    }
    
    ll inv[maxn];//逆元
    ll pre[maxn],pre_inv[maxn];
    
    void init(ll n){//线性求逆元
        inv[0]=inv[1]=1;
        for (int i=2;i<=n;i++){
            inv[i] = ((Mod-Mod/i) *inv[Mod % i]) % Mod;
        }
    }
    
    void init_pre(ll n){//求出1-n的前缀积和逆元前缀积
        pre[0] = pre_inv[0] = 1;
        for (int i=1;i<=n;i++){
            pre[i] = pre[i-1] * i % Mod;
            pre_inv[i] = pre_inv[i-1] * inv[i] % Mod;
        }
    }
    
    ll C(ll n,ll m){
        if(m>n) return 0;
        return pre[n] * pre_inv[m] % Mod * pre_inv[n-m] % Mod;//记得取模
    }
    
    ll Lucas(ll n,ll m){
        if(m==0) return 1;
        return Lucas(n/Mod,m/Mod) * C(n % Mod,m % Mod) % Mod;//记得取模
    }
    
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%lld%lld%lld",&n,&m,&Mod);
            init(n+m);
            init_pre(n+m);
            printf("%lld
    ",Lucas(n+m,n));
        }
        return 0;
    }
    
    你将不再是道具,而是成为人如其名的人
  • 相关阅读:
    微擎模块机制分析2
    微擎we7模块和模板安装方法
    git的使用 及一些常见的错误处理
    人,活着为了什么?
    fedora配置ip
    fedora安装gcc
    linux查看内核版本和发行版本号
    python数据类型2
    python之零碎知识
    python之数据类型1
  • 原文地址:https://www.cnblogs.com/wsl-lld/p/13393531.html
Copyright © 2011-2022 走看看