zoukankan      html  css  js  c++  java
  • 模板

    普通的扩展欧几里得算法,通过了洛谷的扩展欧几里得算法找乘法逆元。修复了容易溢出的bug,虽然新版本仍有可能会溢出longlong,假如参与运算的数字都是longlong,假如可以的话直接使用__int128或者去抄一个RoundGod的BigInt的模板(这里的C题)。事不宜迟明天就抄这个大数模板。
    求解模n意义下a的逆元,即求方程LCE2(a,1,n,x),结果放入x中,返回值指示是否有解。

    ll gcd(ll a, ll b) {
        if(b == 0)
            return a;
        while(ll t = a % b)
            a = b, b = t;
        return b;
    }
    
    ll ex_gcd(ll a, ll b, ll& x, ll& y) {
        if(b == 0) {
            x = 1, y = 0;
            return a;
        }
        ll d = ex_gcd(b, a % b, x, y), t;
        t = x, x = y, y = t - a / b * y;
        return d;
    }
    
    //解线性同余方程 ax + by = c ,无解返回false
    bool LCE1(ll a, ll b, ll c, ll &x0, ll &y0) {
        ll x, y, d = ex_gcd(a, b, x, y);
        if(c % d)
            return false;
        ll k = b / gcd(a, b);
        x0 = ((x % k) * (c / d % k) % k + k) % k;
        y0 = (c - a * x0) / b;
        //x0是x的最小非负整数解
        //x=x0+b*t,y=y0-a*t,是方程的所有解,对所有整数t成立
        return true;
    }
    
    //解线性同余方程 ax = b mod n ,无解返回false
    //和方程 ax + ny = b 等价
    bool LCE2(ll a, ll b, ll n, ll &x0) {
        ll x, y;
        if(LCE1(a, n, b, x, y)) {
            ll k = n / gcd(a, n);
            x0 = (x % k + k) % k;
            //x0是最小非负整数解
            //x=x0+k*t,是方程的所有解,对所有整数t成立
            return true;
        } else
            return false;
    }
    

    未修复的版本理论上会快一点常数,没必要。但是还是做个提醒:

    //解线性同余方程 ax + by = c ,无解返回false
    bool LCE1(ll a, ll b, ll c, ll &x0, ll &y0) {
        ll x, y, d = ex_gcd(a, b, x, y);
        if(c % d)
            return false;
        ll k = c / d;
        x0 = x * k;
        y0 = y * k;
        //x=x0+b*t,y=y0-a*t,是方程的所有解,对所有整数t成立
        return true;
    }
    
  • 相关阅读:
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    RabbitMQ
    .net 5.0
    redis
    分布式同步服务中间件
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/11886449.html
Copyright © 2011-2022 走看看