扩展欧几里得算法
扩展欧几里得算法
欧几里得算法
设$(a,b)==d$,则$d\mid a,d\mid b$。
假设$(b,a%b)==d_1$,则 $d_1\mid a,d_1\mid a%b$
因为$a%b==a-a/b*b$,所以$d\mid a%b$,所以$d_1\ge d$。
假设$d_1>d$,因为$d_1\mid a%b \rightarrow d_1\mid a - a/b * b \rightarrow d1\mid a \and d_1 \mid b$,所以$(a,b)d_1\and d_1>d$与条件不符,因此$(a,b)(b,a%b)d$。$(a,0)a$,所以当有一个为零的时候就可以求出他们的最大公约数了。
可以理解为不断缩小集合的范围然后留下的就是公共的最小得了。
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
扩展欧几里得算法
裴蜀定理
有任意正整数a,b,一定存在非零整数x,y,使得
ax + by = (a,b)
首先左边都整除$d$,所以右边是$d$的倍数,因为他是$d$的倍数,所以最小的就是$d==(a,b)$。
利用扩展欧几里得算法就可以求出这样的$x,y$。
发现求最大共约数的时候当$(r_k,0)==r_k$的时候可以使$x=1,y=0$就求出了一组解。
然后再回溯的时候维护一下就可以。
假设到了当前这一层即
$bx+(a-a/bb)y\rightarrow bx+ay-a/bb*y\rightarrow ay+b(x-a/by)$
只需要回溯的时候维护一下即可
int exgcd(int a, int b, int &x, int &y) {
if (!b) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int k = x;
x = y;
y = k - a / b * y;
return d;
}
我们如果在递归的时候交换一下$x,y$的位置,则有
$by+(a-a/bb)x\rightarrow by+ax-a/bbx \rightarrow ax+b(y-a/bx)$
这样回溯的时候就比较好维护了
int exgcd(int a, int b, int &x, int &y) {
if (!b) {
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= a / b * x;1
return a;
}
我们求出来的是一组不确定的解$x_0,y_0$
通解可以表示为$x=x_0+kb/(a,b),y=y_0-ka/(a,b)$
通解不会改变结果。
求最小正整数解$x$对$b/(a,b)$取模即可。
费马小定理
若有a,p(质数)且(a,p)==1,则有$a^{p-1} \equiv1(mod\ p)$
欧拉定理
若(a,n)==1,则$a^{\varphi(n)}\equiv1(mod\ n)$