前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数

【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数

作者头像
饶文津
发布2020-06-02 15:43:15
1.1K0
发布2020-06-02 15:43:15
举报
文章被收录于专栏:饶文津的专栏饶文津的专栏
1.gcd
代码语言:javascript
复制
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
2.扩展gcd )extend great common divisor
代码语言:javascript
复制
ll exgcd(ll l,ll r,ll &x,ll &y)
{
    if(r==0){x=1;y=0;return l;}
    else
    {
        ll d=exgcd(r,l%r,y,x);
        y-=l/r*x;
        return d;
    }
}
3.求a关于m的乘法逆元
代码语言:javascript
复制
ll mod_inverse(ll a,ll m){
    ll x,y;
    if(exgcd(a,m,x,y)==1)//ax+my=1
        return (x%m+m)%m;
    return -1;//不存在
}

补充:求逆元还可以用

ans = \frac{a}{b} \bmod m = (a \bmod (m\cdot b)) /b
4.快速幂quick power
代码语言:javascript
复制
ll qpow(ll a,ll b,ll m){
    ll ans=1;
    ll k=a;
    while(b){
        if(b&1)ans=ans*k%m;
        k=k*k%m;
        b>>=1;
    }
    return ans;
}
5.快速乘,直接乘会爆ll时需要它,也叫二分乘法。
代码语言:javascript
复制
ll qmul(ll a,ll b,ll m){
    ll ans=0;
    ll k=a;
    ll f=1;//f是用来存负号的
    if(k<0){f=-1;k=-k;}
    if(b<0){f*=-1;b=-b;}
    while(b){
        if(b&1)
            ans=(ans+k)%m;
        k=(k+k)%m;
        b>>=1;
    }
    return ans*f;
}
6.中国剩余定理CRT (x=ai mod mi)
代码语言:javascript
复制
ll china(ll n, ll *a,ll *m) {
    ll M=1,y,x=0,d;
    for(ll i = 1; i <= n; i++) M *= m[i];
    for(ll i = 1; i <= n; i++) {
        ll w = M /m[i];
        exgcd(m[i], w, d, y);//m[i]*d+w*y=1
        x = (x + y*w*a[i]) % M;
    }
    return (x+M)%M;
}
7.筛素数,全局:int cnt,prime[N],p[N];
代码语言:javascript
复制
void isprime()
{
    cnt = 0;
    memset(prime,true,sizeof(prime));
    for(int i=2; i<N; i++)
    {
        if(prime[i])
        {
            p[cnt++] = i;
            for(int j=i+i; j<N; j+=i)
                prime[j] = false;
        }
    }
}
8.快速计算逆元

补充:>>关于快速算逆元的递推式的证明<< 

代码语言:javascript
复制
void inverse(){
    inv[1] = 1;
    for(int i=2;i<N;i++)
    {
        if(i >= M) break;
        inv[i] = (M-M/i)*inv[M%i]%M;
    }
}
9.组合数取模

n和m 10^5时,预处理出逆元和阶乘

代码语言:javascript
复制
ll fac[N]={1,1},inv[N]={1,1},f[N]={1,1};
ll C(ll a,ll b){
    if(b>a)return 0;
    return fac[a]*inv[b]%M*inv[a-b]%M;
}
void init(){//快速计算阶乘的逆元
    for(int i=2;i<N;i++){
        fac[i]=fac[i-1]*i%M;
        f[i]=(M-M/i)*f[M%i]%M;
        inv[i]=inv[i-1]*f[i]%M;
    }
}

n较大10^9,但是m较小10^5时,

代码语言:javascript
复制
ll C(ll n,ll m){
    if(m>n)return 0;
    ll ans=1;
    for(int i=1;i<=m;i++)
        ans=ans*(n-i+1)%M*qpow(i,M-2,M)%M;
    return ans;
}

n和m特别大10^18时但是p较小10^5时用lucas

10.Lucas大组合取模
代码语言:javascript
复制
#define N 100005
#define M 100007
ll n,m,fac[N]={1};
ll C(ll n,ll m){
    if(m>n)return 0;
    return fac[n]*qpow(fac[m],M-2,M)%M*qpow(fac[n-m],M-2,M)%M;//费马小定理求逆元
}
ll lucas(ll n,ll m){
    if(!m)return 1;
    return(C(n%M,m%M)*lucas(n/M,m/M))%M;
}
void init(){
    for(int i=1;i<=M;i++)
        fac[i]=fac[i-1]*i%M;
}

to be continued...

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-07-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.gcd
  • 2.扩展gcd )extend great common divisor
  • 3.求a关于m的乘法逆元
  • 4.快速幂quick power
  • 5.快速乘,直接乘会爆ll时需要它,也叫二分乘法。
  • 6.中国剩余定理CRT (x=ai mod mi)
  • 7.筛素数,全局:int cnt,prime[N],p[N];
  • 8.快速计算逆元
  • 9.组合数取模
  • 10.Lucas大组合取模
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档