【数论】扩展欧几里得算法

扩展欧几里得

    上回刚写完欧几里得,那现在还有一个东西叫拓展欧几里得:

    扩展欧几里得法是一个在求解同余方程等问题上的一个很好的方法,其具体功能如下:

    在已知(a,b)时,求解一组(p,q)使得p*a+q*b=GCD(a,b)

    

    首先,根据数论中的原理,解一定是存在的。

    我们可以设a对于GCD(a,b)的倍数是k,b对于GCD(a,b)的倍数是l

    那么p*(GCD(a,b)*k)+q*(GCD(a,b)*l)=GCD(a,b)

    可以推出:p*k*GCD(a,b)+q*l*GCD(a,b)=GCD(a,b)

    两边同时除以GCD(a,b),可得p*k+q*l=1

    那么我们求解的是一个二元一次不定方程,它是一定有解的。

  

    其次,因为我们知道GCD(a,b)=GCD(b,a%b)

    所以p*a+q*b=GCD(a,b)=GCD(b,a%b)=p*b+q*a%b=q*(a-a/b*b)=q*a+(p-a/b*q)*b

    这样这个方程就化简为了b与a%b的线性组合。

    那么最终的代码是这样的:

#include<iostream>
using namespace std;
int extended_GCD(int a,int b,int &x,int &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    int ans=extended_GCD(b,a%b,x,y);
    int tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ans;//返回的是GCD(a,b)
}
int main(){
    int a,b,x,y,z;
    cin>>a>>b;
    z=extended_GCD(a,b,x,y);
    cout<<z<<" "<<x<<" "<<y;
    return 0;
}

  

时间: 2024-11-05 03:04:26

【数论】扩展欧几里得算法的相关文章

bzoj 3560 DZY Loves Math V - 线性筛 - 数论 - 扩展欧几里得算法

给定n个正整数a1,a2,…,an,求 的值(答案模10^9+7). Input 第一行一个正整数n. 接下来n行,每行一个正整数,分别为a1,a2,…,an. Output 仅一行答案. Sample Input 3 6 10 15 Sample Output 1595 Hint 1<=n<=10^5,1<=ai<=10^7.共3组数据. 题目大意 (题目过于简洁,完全不需要大意) 题目虽然很简洁,但是处处挖着坑等你跳. 原计划两个小时把今天讲的例题A完,实际上两个小时都被这道题

数论-扩展欧几里得算法

证明链接:http://blog.csdn.net/lincifer/article/details/49391175 模板: 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; } 原文地址:https://www.cnblogs.com/TQCAI/p/8455447.html

数论杂谈——欧几里得算法及扩展欧几里得

数学是oi的重要基础,所以说数论在oi中占据了非常重要的地位,因此,学好数学,对于一个oier来说也是非常重要的. oi中的数学,其实也就和数竞并没有什么区别. 欧几里得法辗转相除法求最大公约数 我们可以证明gcd(a,b)=gcd(b,a%b),也就是我国古代数学智慧的结晶,更相损减术.并且一直递归下去,直到b的值为零,最大公约数值即为a.在这里就不给出详细证明了,大家可以代几个数据去验证它一下.谁叫我数学太菜. 代码如下 int GCD(int a,int b) { if(!b) { ret

POJ 1061 青蛙绕地球约会-数论-(解一元一次同余方程+扩展欧几里得算法)

题意:两只青蛙同向跳,起点是x,y,每次分别跳m,n米,地球周长是L,求最少跳几次相遇. 分析: 把式子写好就发现是一个一元一次同余方程.用扩展欧几里得算法来求.这题很基本得会. 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<queue> #define INF 100000

POJ 2115 for求循环次数-数论-(同余方程+扩展欧几里得算法)

题意:给定for循环的初始值,结束值和增量,还有一个模,求最少的循环次数. 分析: 读完题后应该就知道是一个同余的概念,所以就是解一个一元一次同余方程,像上题一样用扩展欧几里得算法.这题的trick点是k最大为32,那么2^32超出了int,要用long long,所以在1<<k时要这样做:1LL<<k,不然就WA了. 代码: #include<iostream> #include<cstdio> #include<algorithm> #inc

数论专题---除法表达式之高精度运算,扩展欧几里得算法

[题意描述] 给定这样一个表达式:X1/X2/X3/·····/Xk,其中Xi是正整数.除法表达式应到按照从左到右的顺序求和.但在表达式中嵌入括号可以改变计算顺序.输入表达式,判断是否可以通过加括号使得表达式最后的值为整数. [分析] 表达式可以写成E=(X1·X3·····Xk)/X2:(X1一定在分子位置,X2一定在分母位置,其它任意) 问题变为E是否为整数. 对于大数相乘,我们可以采用两种方法避免数据溢出: 1.采用素数的唯一分解定理:存储可能存在素数的个数(如何存储,用一个数组就行) 2

数论初步——扩展欧几里得算法

具体内容见紫书p313-p314 一.扩展欧几里得算法 思想:找出一对整数(x,y),使得ax+by=gcd(a,b) 举例:当"a=6,b=15"时,gcd(6,15)=3,故可以得到解"x=3,y=-1",当然还有其他解"x=-2,y=1". 程序: /* 扩展欧几里得算法 */ void gcd(int a, int b, int& d, int& x, int& y) { if(b == 0){ //边界,因为 a

总结——数论:欧几里得算法&amp;扩展欧几里得证明

一 欧几里得辗转相除法算法 设a=qb+r,其中a,b,q,r都是整数,则gcd(a,b)=gcd(b,r),又因 r = a mod b,所以 gcd(a,b)=gcd(b,a mod b). 证明:①证明充分性. 设 d 为 a,b 的公约数,记作 d|a , d|b ,即a和b都可以被d整除 又因 r=a-kb , 两边同时除以d,r/d=a/d-kb/d=m,由等式右边可知m为整数, d|r , 即 d 是 (b,a mod b)的公约数, ②证明必要性 设 d 为 b, a mod b

简单数论总结2——同余方程与扩展欧几里得算法

在上一次总结过后鸽了没多久其实是快要开学赶紧来肝上两篇 今日内容--同余方程和扩展欧几里得算法 同余 同余的定义:若存在两个整数a,b,使得(a - b) MOD P为0,则称作a与b在MOD P的情况下同余 换种通俗的说法,就是,a MOD P与b MOD P相等 记作  \( a\equiv b (mod P) \) 对于整数a,b,c和自然数m,n 同余具有以下性质: 自反性:\( a\equiv a (mod P) \) 对称性:若存在\( a\equiv b (mod P) \) ,则

POJ 1061 青蛙的约会(扩展欧几里得算法)

http://poj.org/problem?id=1061 思路: 搞懂这个扩展欧几里得算法花了不少时间,数论真的是难啊. 含义:找出一对整数,使得ax+by=gcd(a,b). 接下来看这道题目,(x+mt)-(y+nt)=kl,转换成(n-m)t+kl=x-y. 令a=n-m,b=l,c=x-y,那么上式就变成了at+kb=c,之后就参照上面的算法来计算就行,具体参见代码. 1 #include<iostream> 2 #include<algorithm> 3 #inclu