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

        证明略。在此只要求指导exgcd,并且会使用。

        欧几里德算法:现在有a=xb+y,其中a,b,x,y为整数,那么可以得到:gcd(a,b)=gcd(b,a%b)。

     代码实现:

    int gcd(int a,int b)
    {
        return b > 0 ? gcd(b,a%b):a;
    }

      

      扩展欧几里德算法: 对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在无数组整

    数对 x,y ,使得 gcd(a,b)=ax+by。
      证明:
      
        1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
     
        2,a>b>0 时
      设 ax1+ by1= gcd(a,b);  bx2+ (a mod b)y2= gcd(b,a mod b); 
      根据朴素的欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
      则:ax1+ by1= bx2+ (a mod b)y2;
      即:ax1+ by1= bx2+ (a - (a / b) * b)y2=ay2+ bx2- (a / b) * by2;
      也就是ax1+ by1 == ay2+ b(x2- (a / b) *y2);
      根据恒等定理得:x1=y2; y1=x2- (a / b) *y2;
      这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
      上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。
     
     代码实现:
    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
        int r=exgcd(b,a%b,x,y);
        int t=x;
        x=y;
        y=t-a/b*y;
        return r;
    }

        

      应用: 求解不定方程a*x + b*y = c;

      返回的r值就是gcd(a,b)。x,y的值就是方程a*x+b*y = gcd(a,b)的一组解。那么对于要求的方程,x * = c/gcd(a,b); y *= c/gcd(a,b) 现在x,y就是要求的方程的一组解。

    方程的所有解:

      p = x + b/gcd(a,b) * t;

      q = y - a/gcd(a,b) * t; (t为整数)。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<string>
    #include<time.h>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 1000000001
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    using namespace std;
    const int MAXN = 1010;
    int s1,s2,v1,v2,m;
    int gcd(int a,int b)
    {
        return b == 0 ? a : gcd(b,a%b);
    }
    int exgcd(ll a,ll b,ll& x,ll& y)
    {
        if(b == 0){
            x = 1;
            y = 0;
            return a;
        }
        int r = exgcd(b,a%b,x,y);
        int t = x;
        x = y;
        y = t - a / b * y;
        return r;
    }
    int main()
    {
        while(~scanf("%d%d%d%d%d",&s1,&s2,&v1,&v2,&m)){
            if(v1 < v2){
                swap(v1,v2);
                swap(s1,s2);
            }
            int a = v1 - v2;
            int b = m;
            int c = s2 - s1;
            while(c < 0) c += m;
            int d = gcd(a,b);
            //cout<<b<<' '<<d<<endl;
            if(c % d){
                printf("-1
    ");
            }
            else {
                ll x,y;
                exgcd(a/d,b/d,x,y);//将ax + by = c 缩小成a`x + b`y = c` 
                x = (c / d * x) % (b / d);//A'x'+B'y'+(u+(-u))A'B'=1 
                                          //=> (x' + uB')*A' + (y' - uA')*B' = 1
                                          //=>  X = x' + uB', Y = y' - uA'
                                          //可以求得最小的X为(x'+uB') mod B',(x'+uB'>0)
                                          //同时我们还需要将X扩大C'倍,因此最后解为:
                                          //x = (x'*C') mod B'
                while(x < 0){
                    x += (b / d);
                }
                printf("%d
    ",x);
            }
        }
        return 0;
    }
  • 相关阅读:
    一个类GraphQL的ORM数据访问框架发布
    关于 IIS Express 常用设置
    代码失控与状态机(上)
    实体类的动态生成(三)
    实体类的动态生成(二)
    搭建 github.io 博客站点
    实体类的动态生成(一)
    JDK的下载和安装
    三步搞定jupyter nootebook 主题切换
    LeetCode刷题--存在重复元素
  • 原文地址:https://www.cnblogs.com/sweat123/p/5315881.html
Copyright © 2011-2022 走看看