1.拓展欧几里得 + 卢卡斯
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn = 1000000 + 10;
LL n,k;
LL fac[maxn],mod;
LL ex_gcd(LL a,LL b,LL &x,LL &y){//拓展欧几里得
if(b==0){x = 1;y = 0;return a;}
LL ans = ex_gcd(b,a%b,x,y);
LL temp = x;
x = y;
y = temp - (a/b)*y;
return ans;
}
LL inv(LL a){//求逆元
LL x,y;
int ans = ex_gcd(a,mod,x,y);
if(ans!=1)return -1;
if(x<0)x = (x%mod+mod)%mod;
return x;
}
void solve(){
fac[0] = 1;
for(int i = 1;i<=maxn-1;i++){
fac[i] = (fac[i-1]*i)%mod;
}
}
LL comb(LL n,LL k){
if(k>n||n<0||k<0)return 0;
if(n==k||k==0)return 1;
if(k>n-k)k = n-k;
//cout<<fac[n]<<" "<<inv(fac[k])%mod<<" "<<inv(fac[n-k])%mod<<endl;
return (fac[n]*(inv(fac[k])%mod)*(inv(fac[n-k])%mod))%mod;
}
LL Lucas(LL a,LL b){
if(b==0){
return 1;
}
else{
return (comb(a%mod,b%mod)*Lucas(a/mod,b/mod))%mod;
}
}
int main()
{
while(scanf("%lld%lld%lld",&n,&k,&mod)!=EOF){
solve();
printf("%lld\n",Lucas(n,k));
}
return 0;
}
2.费马小定理+卢卡斯
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn = 1000000 + 10;
LL n,k,mod;
LL power(LL a,LL b){
LL ans = 1;
while(b){
if(b&1)ans = (ans*a)%mod;
b>>=1;
a = (a*a)%mod;
}
return ans;
}
LL inv(LL a){//求逆元
return power(a,mod-2)%mod;
}
LL comb(LL a,LL b){
if(a<b) return 0;
if(a==b) return 1;
if(b>a-b) b=a-b;
LL ans=1,ca=1,cb=1;
for(int i=0;i<b;i++){
ca=ca*(a-i)%mod;
cb=cb*(b-i)%mod;
}
ans=ca*inv(cb)%mod;
return ans;
}
LL Lucas(LL a,LL b){
if(b==0){
return 1;
}
else{
return (comb(a%mod,b%mod)*Lucas(a/mod,b/mod))%mod;
}
}
int main()
{
while(scanf("%lld%lld%lld",&n,&k,&mod)!=EOF){
printf("%lld\n",Lucas(n,k));
}
return 0;
}
来源:CSDN
作者:阿阿阿安
链接:https://blog.csdn.net/qq_40772692/article/details/81866373