zoukankan      html  css  js  c++  java
  • 拓展欧几里得算法

    拓展欧几里得算法是用来解决不定方程的整数解的算法


    最大公因数

    众所周知,辗转相除法是解决两个数a,b的最大公因数的方法,记作gcd(a,b)
    每次用a MOD b ,然后将b和模得的数再继续模下去,知道模数为0,也就是b|a
    写成代码是:
    int gcd(int a,int b){
    	retrun b==0 ? a:gcd(b,a%b);
    }

    很简短吧

    拓展欧几里得算法

    现在才是本文的重点
    对于一个关于x和y的方程ax+by=c,我们知道这是一个不定方程,也就是说它的解不唯一

    我们只研究整数解的情况,那么这个方程要么没有整数解,要么有无数个整数解

    如何解?
    1、求解ax+by=gcd(a,b)
    本人很弱,不会证明,所以只给出过程。
    在gcd过程中,当b=0时,x=1,y=0
    否则x=y',y=x'-(a/b)*y'
    这里的除法为整除
    下面是实现代码:
    void exgcd(int a,int b,int& d,int& x,int& y){
    	if(b==0){d=a;x=1;y=0;}
    	else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    }

    2、等式两边乘以c/gcd(a,b)
    我们发现,当上一个方程进行这个操作之后,就会变成我们想要的方程的形式
    a*x*c/gcd+b*y*c/gcd=c
    为了保证整数,当c%gcd!=0时,方程无整数解
    若有解,x=x*c/gcd,y=y*c/gcd

    3、解的周期
    令b0=b/gcd,a0=a/gcd;
    那么
    x'=x+k*b0
    y'=y-k*a0
    就是所有的解
    其中x的最小整数解是(x%b0+b0)%b0

    完整求x最小整数解代码:
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    void exgcd(int a,int b,int& d,int& x,int& y){
    	if(!b) {d=a;x=1;y=0;}
    	else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
    }
    
    int main()
    {
    	int a,b,c,x,y,b0,d;
    	cin>>a>>b>>c;
    	exgcd(a,b,d,x,y);
    	if(c%d) cout<<"No solution!"<<endl;
    	else{
    		x=x*c/d;
    		b0=b/d;
    		cout<<(x%b0+b0)%b0<<endl;
    	}
    	return 0;
    }
    



  • 相关阅读:
    在PHP语言中使用JSON
    PHP数组和Json之间的转换
    Mentohust 安装(win7环境)
    PHP采集网页图片并保存至本地
    php 操作数组 (合并,拆分,追加,查找,删除等)
    GitHub的使用
    【word】含章节号的题注编号以阿拉伯数字显示
    【转载】Mozilla5.0的含义
    同一服务器部署多个Tomcat时的端口号修改详情(同时启动两个Tomcat)
    Android Studio配置
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282890.html
Copyright © 2011-2022 走看看