所有知识点都在《算法导论》数论一部分可以找到。
扩展欧几里得算法求解模线性方程。
ax=b(mod n)
转化到这题就是求解方程Cx = (B-A) (mod 2^k)
自省:判断a不能被b整除用 a%b!=0 不能用a%b>0。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>
using namespace std;
__int64 A,B,C,k;
__int64 extend_gcd(__int64 a,__int64 b, __int64 &x, __int64 &y){
if(b==0){
x = 1;
y = 0;
return a;
}
__int64 d = extend_gcd(b,a%b,x,y);
__int64 tmp = x;
x = y;
y = tmp-a/b*y;
return d;
}
void process(){
__int64 n = (__int64)1 << k;
__int64 b = B-A;
__int64 a = C;
__int64 x,y;
__int64 d = extend_gcd(a,n,x,y);
if(b%d!=0){
cout<<"FOREVER"<<endl;
return;
}
else{
x = (x*(b/d))%n;
x = (x%(n/d)+n/d)%(n/d);
cout<<x<<endl;
return;
}
}
int main(){
while(cin>>A>>B>>C>>k){
if(A==0&&B==0&&C==0&&k==0)
break;
process();
}
return 0;
}