zoukankan      html  css  js  c++  java
  • exgcd扩展欧几里得

    裴蜀定理:对于一对正整数a, b, 存在非零整数x, y使得ax + by = gcd(a, b);

    ax + by 一定是最大公约数gcd(x, y)的倍数。

    1) 如果b = 0,gcd(a, 0) = a, a就是最大公约数ax + by = a. (x = 1, y = 0是一组解) 0和x的最大公约数就是x。

    2)ax + by = gcd(a,b) = gcd(b, a % b)

    by + a % b x = by + (a - a / b * b)x = ax + b(y - a / b * x) = ax + by;

    x不变,y = y - a / b * x;

    所以gcd(a, b, x, y)->gcd(b, a % b, y, x )

    #include <iostream>
    using namespace std;
    
    int exgcd(int a, int b, int &x, int &y)
    {
        if(b == 0)
        {
            x = 1, y = 0;
            return a;
        }
        
        int d = exgcd(b, a % b, y, x);
        
        y -= a / b * x;
        
        return d;
    }
    int main()
    {
        int n;
        cin>>n;
        while(n--)
        {
            int a,b,x,y;
            cin>>a>>b;
            exgcd(a,b,x,y);
            cout<<x<<" "<<y<<endl;
        }
    }

     扩展欧几里得可以求解线性同余方程:

     a ∗ ≡ (mod m)

    ax和b对m的余数相同,简称同余。实际上对于两个数a和b,若存在一个数 m | (a - b), 那么 a ≡ (mod m)

     a ∗ ≡ (mod m)

    存在一个y,使得 ax = my + b, -> ax - my = b, 令y’ = -y, 则有 ax + my’ = b, 就相当于上面的ax + by = gcd(a,b);这里的 b = m;

    #include <cstdio>
    typedef long long LL;
    int exgcd(int a, int b, int &x, int &y)
    {
        if(b == 0)
        {
            x = 1, y = 0;
            return a;
        }
        
        int d = exgcd(b, a % b, y, x);
        
        y -= a / b * x;
        
        return d;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        while(n--)
        {
            int a,b,m;
            scanf("%d%d%d",&a,&b,&m);
            int x, y;
            int d = exgcd(a,m,x,y);
            if(b % d) puts("impossible");
            else printf("%d
    ", x * b / d);
        }
    }

    这里的b一定等于求得的d = gcd(a,m)最大公约数的倍数,得到倍数以后再让求得的原来的系数x乘以这个倍数就得到答案了。

    204. 表达整数的奇怪方式

    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    
    LL exgcd(LL a, LL b, LL &x, LL &y)
    {
        if(!b)
        {
            x = 1, y = 0;
            return a;
        }
        LL d = exgcd(b, a % b, y, x);
        y -= a / b * x;
        
        return d;
    }
    
    int main()
    {
        int n;
        cin>>n;
        bool has_answer = true;
        LL a1, m1;
        cin>>a1>>m1;//先读入第一个方程,然后把后面的所有方程合并进来
        for(int i = 0; i < n - 1; i++)
        {
            LL a2, m2;
            cin>>a2>>m2;
            
            LL k1, k2;
            LL d = exgcd(a1, a2, k1, k2);
            if((m2 - m1) % d) 
            {
                has_answer = false;
                break;
            }
            
            k1 *= (m2 - m1) / d;
            LL t = a2 / d;
            k1 = (k1 % t + t) % t;//把k1变成最小的正整数解
            
            //合并之后新的x = ka + m的解
            m1 = a1 * k1 + m1;
            a1 = abs(a1 / d * a2);//这两部顺序不能变
            
        }
        
        if(has_answer)
        {
            cout<<(m1 % a1 + a1) % a1<<endl;
        }
        else puts("-1");
    }

    x mod a1 = m1, x mod a2 = m2, x mod a3 = m3, ……,x mod an = mn

    我们来试着进行合并,先合并第一和第二个式子:

    x = k1a1 + m1, x = k2a2 + m2

    k1a1 + m1 = k2a2 + m2  ——>>>  k1a1 - k2a2 = m2 - m1;

    通过exgcd扩展欧几里得可以求出一组解(k1, k2),int d = exgcd(a1, a2, k1, k2)返回的是最大公约数,然后 (m2 - m1) / d是扩大的倍数,如果d | (m2 - m1)能够整除就有解,如果不能整除的话就不能没有解。

     构造一个式子:k1 = k1 + k * a2 / d; k2 = k2 + k * a1 / d; 将这个式子带入上面的方程有:

    (k1 + k*a2/d)a1 - (k2 + k*a1/d)a2 = m2 - m1;  k1a1 - k2a2 = m2 - m1;所以是完全等价的。

    所以又有k1 ≡ k1 (mod a2/d), k1 = k1 % (a2 / d), 对一个数%m等于将去整数k倍的m。

    带入 x = k1a1 + m1得到:

    x = (k1 + k*a2 / d)a1 + m1 = k1a1 + m1 + k*a1*a2 / d;

    令a = a1*a2 /d, m = k1a1 + m1, 那么通过两个式子合并之后:x = ka + m, x ≡ m (mod a), x mod a ≡ m, 那么 x = m % a。

    最后a会变成a1, a2, a3,……,an这n个数的公倍数,C++中余数可以为负,-5 % 3 = -2, 可以转化为:(-5 % 3 + 3) % 3 = 1.

    中国剩余定理:

    m1, m2, m3,……,mk两两互质。x ≡ a (mod m).

    x ≡ a1 (mod m1), x ≡ a2(mod m2), x ≡ a3(mod m3),……,x ≡ ak(mod mk)

    令M = m1*m2*……mk, Mi = M / mi(除了mi之外的其他所有m的乘积)所以Mi与mi互质,那么Mi * Mi^-1 ≡ 1 (mod mi),互质的两个数肯定有逆元,

    Mi^-1(Mi % mi的逆元)形如 ax ≡ 1 (mod m)

    通解是: x = (a1 * M1 * M1^-1 + a2M2M2^-1+……+akMkMk^-1)% m1 = a1, 因为M1*M1^-1 mod m1 = 1, 后面的所有Mi都有m1的质因子,所以%m1都为0.

  • 相关阅读:
    方法和参数
    【转】priority_queue优先队列
    【转】主席树学习
    【转】树链剖分
    【转】线段树完全版~by NotOnlySuccess
    【转】树状数组
    【转】最大流EK算法
    【转】POJ题目分类推荐 (很好很有层次感)
    【转】原根
    【转】Polya定理
  • 原文地址:https://www.cnblogs.com/longxue1991/p/12726013.html
Copyright © 2011-2022 走看看