C LooooopsTime Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
for (variable = A; variable != B; variable += C)
statement;
Input
Output
Sample Input
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0
Sample Output
0
2
32766
FOREVER
根据题目的意思,我们可以写出A+C*x=B(mod 2^k),这个同余式,转换一下可以得到
C*x=B-A(mod 2^k),令a=C,b=B-A,n=2^k,得到a*x=b(mod n),然后再在左边加上
b*y,得到a*x+b*y=b(mod n),这时候我们就可以看出来了,应该使用扩展欧几里得来解,扩展欧几里得解决的是a*x+b*y=gcd(a,b),我们先解出两个特解,a0、b0,然后我们讲a*x+b*y=gcd(a,b)左右两边同时乘上b/gcd(a,b),就可以得到a*x+b*y=b(mod n)这个式子,因此我们将a0×(b/gcd(a,b))%n,就可以得到a*x+b*y=gcd(a,b)的特解,我们知道,扩展欧几里得的通解是x=x0+(b/gcd)*t,为了得到最小解,我们可以让
X=(X%(n/gcd)+n/gcd)%(n/d),这个就是最终的解。
#include<iostream> #include<stdio.h> using namespace std; __int64 EXTENDED_EUCLID(__int64 a,__int64 b,__int64& x,__int64& y) { if(b==0) { x=1; y=0; return a; } __int64 d=EXTENDED_EUCLID(b,a%b,x,y); __int64 xt=x; x=y; y=xt-a/b*y; return d; } int main(void) { __int64 A,B,C,k; while(scanf("%I64d %I64d %I64d %I64d",&A,&B,&C,&k)) { if(!A && !B && !C && !k) break; __int64 a=C; __int64 b=B-A; __int64 n=(__int64)1<<k; //2^k __int64 x,y; __int64 d=EXTENDED_EUCLID(a,n,x,y); if(b%d!=0) cout<<"FOREVER"<<endl; else { x=(x*(b/d))%n; x=(x%(n/d)+n/d)%(n/d); printf("%I64d\n",x); } } return 0; }