ACM数论----卢卡斯定理

寵の児 提交于 2019-12-07 12:45:02

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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!