Lucas定理简介(洛谷P3807)

内容

p 为素数,则 C n m C n / p m / p C n   m o d   p m   m o d   p ( mod p )

证明

不会

应用

就是定义式啊。

可以快速判断一个组合数的奇偶。( p = 2

还有一个扩展Lucas,可以解决 p 不是素数的情况(待填坑)。

代码实现

洛谷P3807为例。

递归实现即可。

因为 C n m = n ! m ! ( n m ) ! ,所以要用到逆元。可以线性推,也可以用扩展欧几里得求解。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
using namespace std;
typedef long long LL;
int t,n,m,p; LL c[N],iv[N];
inline void Make(){//线性推逆元
    c[0]=c[1]=iv[0]=iv[1]=1;
    for (int i=2;i<=n+m;i++){
        c[i]=c[i-1]*i%p;
        iv[i]=p-p/i*iv[p%i]%p;
    }
    for (int i=2;i<=n+m;i++)
        iv[i]=iv[i-1]*iv[i]%p; 
}
LL lucas(int x,int y){
    if (x<y) return 0;
    if (x<p) return c[x]*iv[y]%p*iv[x-y]%p;
    return lucas(x/p,y/p)*lucas(x%p,y%p)%p;
}
int main(){
    scanf("%d",&t);
    while (t--){
        scanf("%d%d%d",&n,&m,&p),Make(); 
        printf("%lld\n",lucas(n+m,m));
    }
}

猜你喜欢

转载自blog.csdn.net/a1799342217/article/details/80040126