分析:题目就是要求满足方程A+CX = B(mod 2k次方)的最小X解,当然X>0.
- 也就是Cx + Dy = B-A,其中D = 2k次方,标准的欧几里德扩展,我们利用欧几里德扩展解方程Cx + Dy = gcd(C,D)得到x0,然后方程Cx + Dy = B-A的解x1 = x0/gcd(C,D)*(B-A),当然了,写程序的时候是x1 = x0*(B-A)/gcd(C,D)。
- 求出x1之后,怎么转化为题目要求的最小X呢?x1 = X+cyc*t,如果x1是负值,求余得到的X肯定也是负值,此时x1%cyc+cyc就是正值了。利用周期性((x1%cyc)+cyc)%cyc就可以得到结果了。
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll A,B,C,a,b,c,g,x,y;
int k;
//递归方法一
//int extgcd(int a,int b,int &x,int &y)
//{
// int ans;
// if(b == 0){ ans = a;x = 1;y = 0;}
// else{
// extgcd(b,a%b,x,y);
// int temp = x;
// x = y;
// y = temp-(a/b)*y;
// }
// return ans;
//}
//递归方法二
//int extgcd(int a,int b,int &x,int &y)
//{
// int ans;
// if(b == 0){ ans = a;x = 1;y = 0;}
// else{ ans = extgcd(b,a%b,y,x); y -= (a/b)*x;}
// return ans;
//}
void extgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b){ x = 1; y = 0; d = a;}
else{ extgcd(b,a%b,d,y,x); y -= (a/b)*x;}
return;
}
int main()
{
while(cin >> A >> B >> C >> k,A+B+C+k)
{
a = C;
b = (ll)1<<k;
c = B-A;
extgcd(a,b,g,x,y);
if(c%g) {printf("FOREVER\n");continue;}
ll cyc = b/g;
printf("%lld\n",((x*c/g)%cyc+cyc)%cyc);
}
return 0;
}