zoukankan      html  css  js  c++  java
  • hdu 3037 费马小定理+逆元除法取模+Lucas定理

    组合数学推推推最后,推得要求C(n+m,m)%p

    其中n,m小于10^9,p小于1^5

    用Lucas定理求(Lucas定理求nm较大时的组合数)

    因为p数据较小可以直接阶乘打表求逆元

    求逆元时,由费马小定理知道p为素数时,a^p-1=1modp可以写成a*a^p-2=1modp

    所以a的逆元就是a^p-2,

    可以求组合数C(n,m)%p中除法取模,将其转化为乘法取模
    即    n!/(m!*(n-m)!)=n!*(m!*(n-m)!)^p-2

    求C(n+m,m)。

    n,m<=1000,二维数组递推。

    n,m<=1000000,一维数组预处理出阶乘。

    Lucas适用于n,m较大,MOD较小的情况。

    #include <iostream>
    #define MAX 100005
    
    typedef long long ll;
    using namespace std;
    
    ll mul[MAX],MOD;
    
    void init(){
        mul[0]=1;
        for(int i=1;i<=MOD;i++){
            mul[i]=mul[i-1]*i%MOD;
        }
    }
    ll qMod(ll a,ll b){
        ll ans=1;
        a%=MOD;
        while(b){
            if(b&1) ans=ans*a%MOD;
            b>>=1;
            a=a*a%MOD;
        }
        return ans;
    }
    ll C(ll a,ll b){
        if(a<b) return 0;
        return mul[a]*qMod(mul[b]*mul[a-b],MOD-2)%MOD;
    }
    ll Lucas(ll a,ll b){
        if(b==0) return 1;
        return (C(a%MOD,b%MOD)*Lucas(a/MOD,b/MOD))%MOD;
    }
    int main()
    {
        int T;
        ll n,m;
        cin>>T;
        while(T--){
            cin>>n>>m>>MOD;
            init();
            cout<<Lucas(n+m,m)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    在linux上安装python, jupyter, 虚拟环境(virtualenv)以及 虚拟环境管理之virtualenvwraper
    linux
    Django ORM那些相关操作
    Django 中 form 介绍
    MySQL完整性约束
    git入门
    MySQL表的操作
    努力努力再努力
    Docker初始
    IO模型
  • 原文地址:https://www.cnblogs.com/yzm10/p/8763194.html
Copyright © 2011-2022 走看看