组合数学(费马小定理+卢卡斯定理)模板

组合数取模(费马小定理)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int G = 1000000;
#define mod 1000000007
ll pri[G];
ll ni[G];
ll pow(ll a,ll b,ll m){
    ll ans = 1;
    a %= m;
    while(b){
        if(b&1)ans=(ans%m)*(a%m)%m;
        b /= 2;
        a = (a%m)*(a%m)%m;
    }
    ans %= m;
    return ans;
}

int main(){
  pri[0]=1;
  ni[0]=1;
  for(int i=1;i<G;i++){
    pri[i]=pri[i-1]*i%mod;
    ni[i]=pow(pri[i],mod-2,mod);
  }
  int n,b;
  while(cin>>n>>b){
    ll ans=((pri[n]*ni[b]%mod)*ni[n-b])%mod;
    printf("%lld\n",ans);
  }
}

组合数取模(卢卡斯定理)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
ll n,m,p,fac[maxn];
ll pow(ll x,ll k){
  ll ans = 1;
  while(k){
    if(k&1) ans=ans*x%p;
    k>>=1;
    x=x*x%p;
  }
  return ans;
}
ll C(ll k,ll b){
  if(k<b) return 0;
  return fac[k]*pow(fac[b]%p,p-2)%p*pow(fac[k-b]%p,p-2)%p;
}
ll Lucas(ll k,ll b){
  if(!b) return 1;
  return C(k%p,b%p)*Lucas(k/p,b/p)%p;
}
int main(){
  int t;
  scanf("%d",&t);
  while(t--){
    fac[0]=1;
    scanf("%lld%lld%lld",&n,&m,&p);
    for(int i=1;i<=p;++i){
      fac[i]=fac[i-1]*i%p;
    }
    printf("%lld\n",Lucas(n,m));
  }
  return 0;
}
上一篇:KS02-05 pri 文件有啥用?


下一篇:freecodecamp记录