对于 C 语言的循环语句,形如:
for (variable = A; variable != B; variable += C)
statement;
请问在 k 位存储系统中循环几次才会结束。
若在有限次内结束,则输出循环次数。否则输出死循环。
输入格式
多组数据,每组数据一行四个整数 A,B,C,k。
读入以 0 0 0 0 结束。
输出格式
若在有限次内结束,则输出循环次数。
否则输出 FOREVER。
数据范围
1≤k≤32,
0≤A,B,C<2k
输入样例:
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0
输出样例:
0
2
32766
FOREVER
题解
题意中的k位存储系统是指只保留k位二进制数,那么我们应该
将循环的值对2k取余,因为k位最多就是2k
(
A
+
x
∗
C
)
m
o
d
2
k
=
B
(A + x*C) \mod 2^k = B
(A+x∗C)mod2k=B 求 x 最小值
A
+
x
∗
C
−
y
∗
2
k
=
B
A + x*C - y *2^k= B
A+x∗C−y∗2k=B
x
∗
C
−
y
∗
2
k
=
B
−
A
x*C - y *2^k = B-A
x∗C−y∗2k=B−A 求 x 最小值
此方程用符合裴蜀定理,使用拓展欧几里得算法求解
a
x
+
b
y
=
d
ax+by=d
ax+by=d 的通解为
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
/*
ax+by=c
bx+a%by=c
bx+(a-a/b*b)y=c
bx+ay-a/b*by=c
ay+(x-a/b*y)b=c
*/
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0){
x = 1, y = 0;
return a;
}
LL d = exgcd(b,a%b,y,x);
y -= a/b * x;
return d;
}
int main()
{
LL a,b,c,k;
while(cin>>a>>b>>c>>k){
if(a==0&&b==0&&c==0&&k==0) break;
LL z = 1ll << k;
LL x,y;
LL d = exgcd(c,z,x,y);
if((b-a)%d) cout<<"FOREVER"<<endl;
else {
x *= (b-a)/d;
z /= d;
cout<< (x%z+z)%z<<endl;
}
}
return 0;
}