分析
每次输入a,b,c,k
询问a是否能通过+c得到b(k循环条件下)
$$ a+cx\equiv b \bmod 2^{k} $$
上式等价于:
$$ cx-2^{k}y=b-a $$ 令z=2^{k}得到:
$$ cx-zy=b-a $$
因为要求 x,y 两个未知量 因此使用扩展欧几里得算法exgcd(c,z,x,y)
求出d:$$d=exgcd(c,z,x,y)(d为(c,z)最大公约数)$$
(b-a)如果不为d的倍数,说明不存在这样一个解,输出”FOREVER”
(b-a)为d的倍数的话,要把x,y扩大相应倍数:
$$ x=x\cdot \frac{b-a}{d},y=y\cdot \frac{b-a}{d} $$
此时要求出解x,x等价于:$$ x=x_{0}+k\frac{z}{d} $$
最小的x等价于求x的正余数:(x%z + z) % z
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a,b,c,k;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b)
{
x=1,y=0;
return a;
}
LL d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
while(cin>>a>>b>>c>>k,a||b||c||k)
{
LL x,y;
LL z=(1ll<<k);
LL d=exgcd(c,z,x,y);
cout<<(b-a)<<" "<<d<<endl;
if((b-a)%d) puts("FOREVER"); //(b-a)不是d的倍数,直接退出
else{
x*=(b-a)/d;
y*=(b-a)/d;
z/=d;
cout<<(x%z+z)%z<<endl; //求最小正余数
}
}
return 0;
}