POJ 2115 C Looooops(扩展欧几里得)

题目链接

表示 完全 从学长的文档上照搬的。这才是真正的扩展的欧几里得,以下内容从文档上复制的。

扩展欧几里得的简易证明过程:

 1 如果gcd(a, b) = d 那么一定存在一个整数x, y满足ax+by = d;

 2 

 3 当b == 0时,显然,x = 1, y = 0. d = a;

 4 当b != 0时, 设

 5   a*x1 + b*y1 = d ;(d = gcd(a, b))

 6   b*x2 + (a%b)*y2 = d;

 7 所以

 8   a*x1 + b*y1 = b*x2 + (a – [a/b]*b)*y2

 9   a*x1 + b*y1 = a*y2 + b*(x2 – [a/b]*y2)

10 所以

11   x1 = y2;

12   y1 = x2 – [a/b]*y2

13 

14 扩展欧几里德算法可以用来判断整数点是否在直线上,因为直线方程有ax + by + c = 0

这个题的解题思路:

1 从题目中可以得到方程:

2 

3 a + c*x = b (mod 2^k) 

4 变形得

5 c*x = (b-a) (mod 2^k);

6 再变形得:

7  c*x – 2^k*y = (b – a) 

8 

9 解扩展欧几里德方程就可以了

代码:

 1 #include <stdio.h>

 2 #include <string.h>

 3 #include <stdlib.h>

 4 __int64 p[60],x,y;//不知道为何地址传递的时候会CE,所以直接搞个全局变量

 5 __int64 ext_eulid(__int64 a,__int64 b)

 6 {

 7     __int64 t,d;

 8     if(b == 0)

 9     {

10         x = 1;

11         y = 0;

12         return a;

13     }

14     d = ext_eulid(b,a%b);

15     t = x;x = y;y = t - (a/b)*y;

16     return d;//返回的ax + by = d方程中的d

17 }

18 int main()

19 {

20     __int64 i,k,n,a,b,c,d,sum;

21     p[0] = 1;

22     for(i = 1;i <= 32;i ++)

23     {

24         p[i] = 2*p[i-1];

25     }

26     while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&k)!=EOF)

27     {

28         if(!a&&!b&&!c&&!k) break;

29         n = p[k];

30         if(b - a < 0)

31         b = ((b-a) % n + n)%n;//存b-a,b-a必须大于等于0

32         else 

33         b = b - a;

34         d = ext_eulid(c,n);

35         if(b%d)//如果b不是d的整数倍,则无解。

36         {

37             printf("FOREVER\n");

38             continue;

39         }

40         n = n/d;

41         sum = (x*(b/d)%n+n)%n;//实际上x*(b/d)为答案,为了防止变为负数,再对n取余,因为b/d,n也要变为n/d;

42         printf("%I64d\n",sum);

43     }

44     return 0;

45 }

 

 

你可能感兴趣的:(oop)