题目大意
给你四个数 A B C k 问你 for(int i=A;i!=B;i+=C) 语句循环的次数,死循环就输出FOREVER,所有的数字都是 k−bit unsigned integer , mod 2k (也就是 0≤A,B,C<2k,k≤32 )
分析
将问题换一种简单的问法也是帮助思考的比较好的技巧
这道题的意思是:问A加几个C
(mod 2k)
可以变成B
用数学表达就是:求一个最小的x使得
(A+xC) mod 2k=B
其实就是求解一元线性同余方程:
xC≡(B−A) (mod 2k)
这道题就是一个基础的解一元线性同余方程的模板题了
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
typedef long long int LL;
LL Gcd(LL a,LL b)
{
return b==0?a:Gcd(b,a%b);
}
LL Exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
else
{
LL ans=Exgcd(b,a%b,x,y);
LL temp=x;
x=y;
y=temp-(a/b)*y;
return ans;
}
}
LL f(LL a,LL b,LL m)//求解一元线性同余方程
{
LL x,y,d;
d=Exgcd(a,m,x,y);
if(b%d!=0)return -1;
x=x*(b/d)%m;
x=(x%(m/d)+(m/d))%(m/d);
return x;
}
int main()
{
LL A,B,C,k;
while(scanf("%I64d %I64d %I64d %I64d",&A,&B,&C,&k)!=EOF)
{
if(A==0 && B==0 && C==0 && k==0)break;
LL ans=f(C,B-A,pow(2,k));
if(ans==-1)cout<<"FOREVER"<<endl;
else cout<<ans<<endl;
}
return 0;
}