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=0; return 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 }
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=0; return 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 }