• [模板] 常用数论 -> gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数


    1.gcd
    ll gcd(ll a, ll b)
    {
        return b ? gcd(b, a % b) : a;
    }
     
    
    2.扩展gcd )extend great common divisor
     
    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的乘法逆元
     
    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=abmodm=(amod(m⋅b))/b
    4.快速幂quick power
     
    ll qpow(ll a, ll b, ll m)
    {
        ll ans = 1;
        ll k = a % mod;
        while(b)
        {
            if(b & 1)
                ans = ans * k % m;
            k = k * k % m;
            b >>= 1;
        }
        return ans;
    }
     
    
    5.快速乘,直接乘会爆ll时需要它,也叫二分乘法。
     
    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)
     
    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];
     
    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.快速计算逆元
    补充:>>关于快速算逆元的递推式的证明<< 
    
     
    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时,预处理出逆元和阶乘
    
     
    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时,
    
     
    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大组合取模 
    
    #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;
    }

     PY版CRT

    def gcd(a, b):
        if(b == 0):
            return a
        else:
            return gcd(b, a % b)
     
    def ex_gcd(dividend, divisor):
        if 0 == divisor:
            return 1, 0, dividend
        x2, y2, remainder = ex_gcd(divisor, dividend % divisor)
        temp = x2
        x1 = y2
        y1 = temp - int(dividend // divisor) * y2
        return x1, y1, remainder
     
    rs1, rs2 = input().split()
    n = int(rs1)
    mx = int(rs2)
     
    ai = []
    bi = []
     
    def ex_crt():
        M = bi[0]
        ans = ai[0]
        for i in range(1, n):
            a = M
            b = bi[i]
            c = (ai[i] - ans % b + b) % b
            g = gcd(a, b)
            x = ex_gcd(a, b)[0]
            bg = b // g
            if (c % g != 0):
                return -1
     
            x = (x * (c // g) % bg)
            ans = ans + x * M
            M = M * bg
            ans = (ans % M + M) % M
     
        ans = (ans % M + M) % M;
        return ans
     
     
    for i in range(n):
        s1, s2 = input().split()
        bi.append(int(s1))
        ai.append(int(s2))
     
    res = ex_crt()
     
    if(res == -1):
        print("he was definitely lying")
         
    elif(res <= mx):
        print(res)
         
    else:
        print("he was probably lying")
  • 相关阅读:
    实现一个基于tcc/tlink的简单的编译链接工具
    从函数指针数组的运用来看程序结构化设计(2)
    从函数指针数组的运用来看程序结构化设计
    crypt()函数
    PHP fopen()函数 打开文件
    PHP 数据库访问
    php中图像处理的常用函数
    PHP Cookie的用法
    Spring的依赖注入
    拦截器
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270419.html
Copyright © 2020-2023  润新知