盧卡斯定理(n≤10^18,m≤10^18,p≤10^5)

Lucas定理是用於處理組合數取模的定理,當m,n較大時使用
在這裏插入圖片描述
它可以將一個大組合數取模,轉化成很多小組合數相乘取模(n<p, m<p)

模板:

LL Lucas(LL n,LL m,LL p)
{
    if(!m) return 1;
    return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}

例題:P3807 【模板】盧卡斯定理

代碼:
求後面的小組合數,可以將下面公式中分子的逆元求出來,轉化爲乘積
在這裏插入圖片描述

#include <iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#define mod 1000000007
#include<string.h>
using namespace std;
typedef long long LL;
const int manx=1e5+7;
LL a[manx];
LL quick_pow(LL a,LL b,LL m)
{
     LL ans=1;
     while(b)
     {
          if(b&1)
               ans=(ans*a)%m;
          a=(a*a)%m;
          b>>=1;
     }
     return ans;
}
LL C(LL n,LL m,LL p)
{
    if(m>n)return 0;
    return ((a[n]*quick_pow(a[m],p-2,p))%p*quick_pow(a[n-m],p-2,p)%p);
}
LL Lucas(LL n,LL m,LL p)
{
    if(!m) return 1;
    return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
int main()
{
     LL n,m,p,t;
     scanf("%lld",&t);
     a[0]=1;
     while(t--)
     {
          scanf("%lld%lld%lld",&n,&m,&p);
          for(int i=1;i<=p;i++)a[i]=(a[i-1]*i)%p;
          printf("%lld\n",Lucas(n+m,m,p));
     }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章