Processing math: 16%

关于Euclid算法

Euclid算法大概是我最早接触的东西了吧,下面是学长传授的代码:

1 int GCD(int a,int b){
2     return b==0?a:GCD(b,a%b);   
3 }

短小精悍。当时也没理解为什么这段代码可以求出ab的最大公因数。现补下证明。

ab的最大公因数记为gcd(a,b),简写为(a,b).

证明Euclid算法的正确性,即证明(a,b)=(a,bka).

x=(a,b)y=(a,bka)

\therefore x|ax|b

\therefore x|(-ka+b)

\therefore x|(a,b-ka)=y

x \leqslant y.

\because y=(a,b-ka)

\therefore y|ay|(b-ka)

\therefore y|[ka+(b-ka)]=b

\therefore y|(a,b),即y|x

y \leqslant x.

\therefore x=y.

(a,b)=(a,b-ka).证毕.

k=\lfloor \frac{a}{b} \rfloor时,即为Euclid算法.

 

上述Euclid算法仅求出(a,b),而不能得到(a,b)关于ab的线性表示,故有了拓展的Euclid算法:

 1 int EXGCD(int a,int b,int &x,int &y){
 2     if(b==0){
 3         x=1;y=0;
 4         return a;
 5     }
 6     int d=EXGCD(b,a%b,x,y);
 7     int t=x;
 8     x=y;y=t-a/b*y;
 9     return d;
10 }

上述算法可求得xy,使满足(a,b)=ax+by.

为便于证明,以非递归版本为例:

 1 int EXGCD(int a,int b,int &x,int &y){
 2     int x0=1,x1=0,x2=a;
 3     int y0=0,y1=1,y2=b;
 4     while(y2!=0){
 5         int q=x2/y2;
 6         int t0=x0,t1=x1,t2=x2;
 7         x0=y0;x1=y1;x2=y2;
 8         y0=t0-q*y0;y1=t1-q*y1;y2=t2-q*y2;
 9     }
10     x=x0;y=x1;
11     return x2;
12 }

ax_0+bx_1=x_2ay_0+by_1=y_2

不难得到a(x_0-qy_0)+b(x_1-qy_1)=x_2-qy_2.

上述等式正式保证了拓展Euclid算法的正确性。

 

拓展Euclid算法可用来求模线性方程ax+by=(a,b)的解。

特别地,当(a,b)=1时,x即为ab下的乘法逆元。

 

1n的数在p下的乘法逆元可以做到O(n)的复杂度:

inv_iip下的逆元,则有inv_x \equiv [(p- \lfloor \frac{p}{x} \rfloor ) \times inv_{p\%x}](mod p).

证明:设p=kx+r,其中0 \leqslant r < x

那么原式等于inv_x \equiv [(p-k) \times inv_r](mod p)

\Leftarrow r \equiv [(p-k) \times x](mod p)

\Leftarrow r \equiv -kx(mod p)

kx+r \equiv p \equiv 0(mod p),证毕.

故我们可以递推得到各个逆元。

posted @ 2017-03-14 01:43  barriery  阅读(1277)  评论(1编辑  收藏  举报