C Looooops POJ - 2115

题目:

A Compiler Mystery: We are given a C-language style for loop of type

  statement; ```

I.e., a loop which starts by setting variable to value A and while
variable is not equal to B, repeats statement followed by increasing
the variable by C. We want to know how many times does the statement
get executed for particular values of A, B and C, assuming that all
arithmetics is calculated in a k-bit unsigned integer type (with
values 0 <= x < 2k) modulo 2k.

Input

The input consists of several instances. Each instance is described by
a single line with four integers A, B, C, k separated by a single
space. The integer k (1 <= k <= 32) is the number of bits of the
control variable of the loop and A, B, C (0 <= A, B, C < 2k) are the
parameters of the loop.

The input is finished by a line containing four zeros.

Output

The output consists of several lines corresponding to the instances on
the input. The i-th line contains either the number of executions of
the statement in the i-th instance (a single integer number) or the
word FOREVER if the loop does not terminate.

Sample Input
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0
Sample Output
0
2
32766
FOREVER

题意:

初始值为A,每次可以增加C,值要mod2^k^,问mod后的值如果等于B,增加了几次C,如果无法等于B输出FOREVER

题解:

看一下我的推导:
在这里插入图片描述
你会发现其实就是扩展欧几里得的模板题,并求出最小正整数解
我们可以用 (x0 % b1 + b1 ) % b1得到它的最小正整数解了
此处x0= x * c / gcd(a,b)
详细证明看下面博客
扩展欧几里得讲解

代码:

#include<iostream>
#include<vector>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<list>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得算法
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;  //到达递归边界开始向上一层返回
    }
    ll gcd=exgcd(b,a%b,x,y);
    ll y1=y;    //把x y变成上一层的
    ll x1=x;
    y=x1-(a/b)*y1;
    x=y1;
    return gcd;     //得到a b的最大公因数
}

int main()
{
    ll A,B,C,K;
    while(cin>>A>>B>>C>>K)
    {
        if(A==0&&B==0&&C==0&&K==0)break;
        ll x,y;
        ll a=C;
        ll b=(ll)1<<K;
        ll c=B-A;
        ll gcd=exgcd(a,b,x,y);
        if(c%gcd!=0)
        {
            cout<<"FOREVER"<<endl;
        }
        else {
             x=(x*(c/gcd))%b;
             x=(x%(b/gcd)+b/gcd)%(b/gcd);
            cout<<x<<endl;
        }
    }
    return 0;
}