Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5771889
  • 博文数量: 675
  • 博客积分: 20301
  • 博客等级: 上将
  • 技术积分: 7671
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-31 16:15
文章分类

全部博文(675)

文章存档

2012年(1)

2011年(20)

2010年(14)

2009年(63)

2008年(118)

2007年(141)

2006年(318)

分类:

2006-10-10 08:47:29

扩展欧几里得算法- -
                                       

因为要用这个算法来计算逆元,所以写一下
扩展欧几里得算法:

欧几里得算法中,计算 x, y 的最大公约数的方法是辗转相除,例如:

gcd (
2615)

26 % 15 = 1  11
15 % 11 = 1  4
11 % 4 = 2  3
4 % 3 = 1  1
3 % 1 = 3  0 

可知,gcd (
2615= 1

如果 gcd(x, y) 
= r,那么有 ax + by = r,可以看出,上面的步骤实际上是可以直接得出 a, b 的:
null
26 % 15 = 1  11 => 11 = 26 - 15 1 1 -1
15 % 11 = 1  4 => 4 = 15 - 11 = 15 - (26 - 15= -26 + 2*15 1 -1 2
11 % 4 = 2  3 => 3 = 11 - 4*2 = (26 - 15- (-26 + 15* 2 = 3*26 - 5*15 2 3 -5
4 % 3 = 1  1 => 1 = 4 - 3 = (-26 + 2*15- (3*26 - 5*15= -4*26 + 7*15 1 -4 7
3 % 1 = 3  0 

在每一轮,我们都可以得到一个模的表达式为:ri 
= aix + biy
如果不考虑第一轮和第二轮,那么ai 和 bi 可以表示为(qi 为每一轮得到的商):

ai 
= ai-2 - qi * ai-1
bi 
= bi-2 - qi * bi-1

现在来考虑第一轮和第二轮,按照上面的公式,可以认为

a
-1 = 1, b-1 = 0
a0 
= 0, b0 = 1

有了这两对预设值,上面的两个公式就成立了

求逆元,由上面可以看出,gcd(x, y) 
= 1 的时候
如果 ax 
+ by = 1,那么 ax = -by + 1 => ax = 1 (mod b)
这时候,a 即是 x 的逆元


1 #include 
2
3  int gcd (int x, int y, int *a1, int *a2, int *b1, int *b2)
4  {
5    int q, r, a, b;
6
7    q = x / y;
8    r = x % y;
9
10    a = *a2 - q*(*a1);
11    b = *b2 - q*(*b1);
12
13    if (0 == r)
14      {
15        return y;
16      }

17
18    *a2 = *a1;
19    *b2 = *b1;
20
21    *a1 = a;
22    *b1 = b;
23
24    return gcd (y, r, a1, a2, b1, b2);
25  }

26
27  int main (int argc, char *argv[])
28  {
29    int x, y, a1, a2, b1, b2, r;
30
31    x = atoi (argv[1]);
32    y = atoi (argv[2]);
33
34    a1 = 0;
35    a2 = 1;
36    b1 = 1;
37    b2 = 0;
38
39    r = gcd (x, y, &a1, &a2, &b1, &b2);
40
41    printf ("%d = (%d) * (%d) + (%d) * (%d)\n",
42            r, a1, x, b1, y);
43
44    return 0;
45  }
阅读(2968) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~