exgcd 解决的问题:
求出a*x+b*y=c(a,b,c为常量)的一组解,时间复杂度log(a)
首先先做一个证明
a*x+b*y=c 有整数解的充要条件是c整除gcd(a,b)
设gcd(a,b)=p
1.充分性:
a*x+b*y=c
a'*p*x+b'*p*y=c(a'=a/p)
p(a'*x+b'*y)=c;
因为x,y必须为整数
所以c必须整除p
2.必要性
使用欧几里得和数学归纳法可证明
首先b*x1+(a%b)*y1=c,有整数解,则a*x2+b*y2=c有整数解
a*x2+b*y2=b*x1+(a%b)*y1=b*x1+(a-floor(a/b)*b)*y1=a*y1+b*(x1-floor(a/b)*y1);floor表示向下取整
然后就可以得到对应关系x2=y1,y2=(1-floor(a/b))*y1;
显然最后的p,0有解
所以求这个a*x+b*y=c整数解的过程只需要不断递归运行到底层即可
最后一层p*x+0*y=c的解为x=c/p,y=0;之后再不断用关系x2=y1,y2=(x1-floor(a/b)*y1)推出上一层的解即可
例题:noip2012同余方程
https://www.luogu.org/problemnew/show/P1082
题目描述
求关于xx的同余方程 a x \equiv 1 \pmod {b}ax≡1(modb) 的最小正整数解。
输入输出格式
输入格式:
一行,包含两个正整数 a,ba,b,用一个空格隔开。
输出格式:
一个正整数 x_0x0,即最小正整数解。输入数据保证一定有解。
输入输出样例
说明
【数据范围】
对于 40%的数据,2 ≤b≤ 1,0002≤b≤1,000;
对于 60%的数据,2 ≤b≤ 50,000,0002≤b≤50,000,000;
对于 100%的数据,2 ≤a, b≤ 2,000,000,0002≤a,b≤2,000,000,000。
NOIP 2012 提高组 第二天 第一题
其实就是求ax+by=1的最小整数解
记得最后求出的x还要化为最小整数
#include<cstdio> int x,y; void exgcd(int a,int b){ if(!b) x=1,y=0; else{ exgcd(b,a%b); int tx=y,ty=x-a/b*y; x=tx,y=ty; } } int main(){ int a,b; scanf("%d%d",&a,&b); exgcd(a,b); x%=b;x+=b,x%=b; printf("%d",x); return 0; }