洛谷——P3807 【模板】卢卡斯定理

P3807 【模板】卢卡斯定理

洛谷智推模板题,qwq,还是太弱啦,组合数基础模板题还没做过。。。

给定n,m,p($1\le n,m,p\le 10^5$)

求 $C_{n+m}^{m}\ mod\ p$

$lucas$定理:

$C_{n}^{m}=C_{n\%p}^{m\%p}\times C_{n/p}^{m/p}\mod p$

相当于把$n,m$写成$p$进制数($A_1,A_2\dotso A_k$),($B_1,B_2\dotso B_k$)

$C_{n}^{m}=C_{A_1}^{B_1}\times C_{A_2}^{B_2}\times \dots \times C_{A_k}^{B_k}$

证明略。。。(还不是因为博主弱,不会证吗。。。) 

Lucas+费马小定理

#include<iostream>
#include<cstdio>
#include<algorithm>

#define N 200004
#define LL long long
using namespace std;

LL f[N];

LL pow(LL a,LL b,LL p){
    LL s=1;
    for(;b;b>>=1,a=a*a%p)
        if(b&1) s=s*a%p;
    return s;
}

LL C(LL n,LL m,LL p){
    if(m>n) return 0;
    return (f[n]*pow(f[m],p-2,p))%p*(pow(f[n-m],p-2,p)%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;
}

LL T,n,m,p;

int main()
{
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&n,&m,&p);
        f[0]=1;
        for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p;
        printf("%lld\n",lucas(n+m,m,p));
    }
    
    return 0;
}

lucas+逆元

#include<iostream>
#include<cstdio>
#include<algorithm>

#define N 200004
#define LL long long
using namespace std;

LL f[N],inv[N];


LL lucas(LL n,LL m,LL p){
    if(n<m) return 0;
    else if(n<p) return f[n]*inv[m]*inv[n-m]%p;
    else return lucas(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
}

LL T,n,m,p;

int main()
{
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&n,&m,&p);
        f[0]=f[1]=inv[1]=inv[0]=1;
        for(int i=2;i<=p;i++) f[i]=f[i-1]*i%p;
        for(int i=2;i<=p;i++) inv[i]=(p-p/i)*inv[p%i]%p;
        for(int i=2;i<=p;i++) inv[i]=inv[i]*inv[i-1]%p;
        printf("%lld\n",lucas(n+m,m,p));
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/song-/p/9776026.html