HDU3037-卢卡斯(Lucas)定理模板

前言:

 写上一个题的时候用到组合数了,就去百度了下,在此更新一下。

typedef long long LL;
const LL md = 1e9 + 7;
const int maxn = 1e5 + 10;
LL ar[maxn],sum[maxn];
const int N = 100007;
LL f[N];
LL quickpow(LL a,LL b,LL m){
    LL ans=1;
    while (b!=0){
        if (b%2==1){
            ans=ans*a%m;
            b--;
        }
        a=a*a%m;
        b=b/2;
    }
    return ans;
}
//数据范围较小的组合数
LL yes(LL n,LL m){
    if (n<m){
        return 0;
    }
    if (m>n-m){
        m=n-m;
    }
    LL s1=1,s2=1;
    LL i;
    for (i=1;i<=m;i++){
        s1=s1*(n-i+1)%md;
        s2=s2*i%md;
    }
    return s1*quickpow(s2,md-2,md)%md;
}
LL lucas(LL n,LL m){
  if (m==0){
    return 1;
  }
  return (lucas(n/md,m/md)*yes(n%md,m%md)%md);
}


HDU3037:传送门

//一般p在1e6以下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
#include <cmath>
#include <sstream>
using namespace std;
typedef long long LL;
int p;
inline void read(int &x){
    x = 0; char ch = getchar(), c = ch;
    while(ch < '0' || ch > '9') c = ch, ch = getchar();
    while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
    if(c == '-') x = -x;
}
inline LL exp_mod(LL a,int b){
    LL ret=1;
    while(b){
        if(b&1){
            ret=ret*a%p;
        }
        a=a*a%p;
        b>>=1;
    }
    return ret;
}
LL comb(int n, int m){
    if(m==0)return 1;
    LL x=1, y=1;
    m=min(m,n-m);
    for(int i=0;i<m;++i){
        x=x*(n-i)%p;
        y=y*(m-i)%p;
    }
    return x*exp_mod(y,p-2)%p;
}
LL lucas(int n, int m){
    if(n<m)return 0;
    if(n < p && m < p)return comb(n, m);
    return lucas(n % p, m % p) * lucas(n / p, m / p) % p;
}
int main(){
    int T;
    read(T);
    while(T--) {
        int n, m;
        read(n);read(m);read(p);
        printf("%lld\n", lucas(n + m, m));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/81143656
今日推荐