POJ2115 (扩展欧几里德)

刚看完题后,没有想到要用欧几里德算法求解,觉得只是道简单的数论。后来发现问题了,就开始找原因。

解题思路:这道题和POJ1061(青蛙约会)一样,都是同余方程的求解,用到了拓展欧几里德算法。而本题题意明确,就是求解这个公式:(a+c*x)mod2^k=b ,求得x 的最小解。变形后可得:c*xmod2^k=b-a,即 c*x=(b-a)mod2^k; 这就是标准的同余方程。

注意:k <=32 ,而 2的 32次方超出整数范围,所以要用__int64或long long ,就不会出现runtime error了。

其实数论真得很神奇,一变形就是我们所熟悉的知识。看来还是我见得少,练得少,下次一定要长点儿心了,像这样的题不能说不会吧!

代码如下:

View Code
 1 #include<stdio.h>
 2 __int64 f(int k) //求2 的 k 次方
 3 //注意:k超过30位整型要用64位
 4     __int64 sum=1;
 5     for(int i=0;i<k;i++)
 6         sum*=2;
 7     return sum;
 8 }
 9 
10 __int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y)//拓展欧几里德算法
11 {
12    __int64 d,t;
13    if(b==0) { x=1; y=0return a; }
14    d=exGcd(b,a%b,x,y);
15    t=x; x=y; y=t-a/b*y;
16    return d;
17 }
18 int main()
19 {
20      __int64 a,b,c,x,y,d,r;
21      int k;
22      while(scanf("%I64d%I64d%I64d%d",&a,&b,&c,&k))
23      {
24          if(a==0&&b==0&&c==0&&k==0)
25              break;
26          d=exGcd(c,f(k),x,y);
27          if((b-a)%d!=0) printf("FOREVER\n");
28          else{
29             x=x*(b-a)/d;
30             r=f(k)/d;
31             x=(x%r+r)%r;
32             printf("%I64d\n",x);
33          }
34      }
35      return 0;
36 }

posted @ 2011-08-27 16:44  笑巧  阅读(1518)  评论(0编辑  收藏  举报