正题
链接:
http://poj.org/problem?id=2115
大意
就是给出个循环
for(i=A;i!=B;i=(i+C)mod2k)
f
o
r
(
i
=
A
;
i
!
=
B
;
i
=
(
i
+
C
)
m
o
d
2
k
)
求需要循环次数
解题思路
我们定义
l=2k
l
=
2
k
首先可以推出:
Cx+A≡B(modl)
C
x
+
A
≡
B
(
m
o
d
l
)
然后解mod
Cx+A=B+lk
C
x
+
A
=
B
+
l
k
然后定义 y=−l y = − l ,移项
Cx+ly=B−A
C
x
+
l
y
=
B
−
A
然后我们定义 d=gcd(C,l) d = g c d ( C , l ) ,之后同时除去d
Cx/d+ly/d=(A−B)/d
C
x
/
d
+
l
y
/
d
=
(
A
−
B
)
/
d
因为d是C和l的最大公约数那么因为
C
C
%,
l
l
%,所以只要
(A−B)
(
A
−
B
)
%
d=0
d
=
0
这个方程就有解
之后因为这样求出的x不是最大解所以我们要:
定义
g=(l/d)
g
=
(
l
/
d
)
然后
(x∗((B−A)/d) ( x ∗ ( ( B − A ) / d ) % g+g) g + g ) % g g <script type="math/tex" id="MathJax-Element-28">g</script>
求出最小解
代码
#include<cstdio>
using namespace std;
long long x,y,d,a,b,c,k;
long long gcdup(long long a,long long b)
{
if (b==0)
{x=1;y=0;return a;}
d=gcdup(b,a%b);
long long k=x;
x=y;
y=k-a/b*y;
return d;
}
int main()
{
while (true)
{
scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
if (a==0 && b==0 && c==0 && k==0) break;
k=1ll<<k;
d=gcdup(c,k);
if ((b-a)%d) printf("FOREVER\n");
else printf("%lld\n",(x*((b-a)/d)%(k/d)+(k/d))%(k/d));
}
}