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; }