题意:求for (variable = A; variable != B; variable += C)的循环次数,其中变量为k比特无符号整数。
求解形如 ax=b(mod n)的方程,对于整数x来说,方程要么无解,无数个解。
如果表示成对应等价类[a]n *[x]n = [x*b]n,x∈[0,n-1]。([a]n代表x%n=a.的所有满足条件的x所组成的集合,其中a为集合中最小非负整数,用最小的非负整数来代表整个集合,即[a]n={a+k*n,k∈Z)})
对于集合来说只有一个解[x0]n.
无数个解无意义,一般讨论在0~n-1上有多少解。
将ax=b(mod n)=> ax+ny=b。
如果b不是d=gcd(a,n)的倍数,方程无解
否则在0~n-1上有d个解,任意两个解与n/d同余(x0=x+k*(n/d))
题目中:解出的x0不一定是最小非负的,将其转化成最小非负解即是答案
思路: (a + c*x)% 2^k = b; cx = b-a (mod 2^k) ,=> cx + 2^k*y=(b-a)求解模线性方程,x取最小正整数解
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b)
{
d=a;
x=1;y=0;
}
else
{
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}
int main()
{
ll A,B,C,k;
// freopen("in.txt","r",stdin);
while(~scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k))
{
if(A+B+C+k==0)break;
ll b=(ll)1<<k; // k位的最大数字是(1<<k)-1 但是这里是取1<<k
ll a=C;
ll c=B-A;
ll d,x,y;
exgcd(a,b,d,x,y);
if(c%d)
{
printf("FOREVER\n");
}
else
{
x*=(c/d);
ll t=b/d;
if(t<0)t=-t;
x=(x%t+t)%t;
printf("%I64d\n",x);
}
}
}