正题
链接:
http://poj.org/problem?id=2115
大意
就是给出个循环
for(i=A;i!=B;i=(i+C)mod2k)for(i=A;i!=B;i=(i+C)mod2k)
求需要循环次数
解题思路
我们定义l=2kl=2k
首先可以推出:
Cx+A≡B(modl)Cx+A≡B(modl)
然后解mod
Cx+A=B+lkCx+A=B+lk
然后定义y=−ly=−l,移项
Cx+ly=B−ACx+ly=B−A
然后我们定义d=gcd(C,l)d=gcd(C,l),之后同时除去d
Cx/d+ly/d=(A−B)/dCx/d+ly/d=(A−B)/d
因为d是C和l的最大公约数那么因为CC%,ll%,所以只要(A−B)(A−B)%d=0d=0这个方程就有解
之后因为这样求出的x不是最大解所以我们要:
定义g=(l/d)g=(l/d)
然后
(x∗((B−A)/d)(x∗((B−A)/d)%g+g)g+g)%gg<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));}
}