[数论] Looooops

题目传送门:http://poj.org/problem?id=2115


Description

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

for (variable = A; variable != B; variable += C)     
    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.

题目大意:给定一个循环

for(int i=A;i!=B;i+=C) statement;

其中,当循环变量的值大于2^k,就对2^k取模。
问:在循环结束之后,i的值是多少?
若循环不能结束,输出“FOREVER”
A,B,C,K为输入的值,输入数据以”0 0 0 0”结束.


题解

根据题意,我们可以列出一个方程来表示这个循环的过程:
(A+xC)%d=B (d=2^k)
进行适当变形得:
A+xC=B+yD
xC-yD=B-A
到这里就很明了,一个二元一次方程求解,首先想到拓展欧几里得算法,算出xC-yD=GCD(C,D)的解。
如果(B-A)%GCD(C,D)!=0,说明原方程无整数解,输出FOREVER
否则,对解x进行如下操作:ans=(x*abs((B-A)/GCD(C,D)))%d+d
(由于GCD(C,D)与(B-A)成倍数关系,所以原方程的解也要翻这么多倍,并保证x为正数)


代码

#include
#include
#define ll long long
using namespace std;
int extGcd(ll a,ll b,ll &x,ll &y)
{
    int ans,tmp;
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ans=extGcd(b,a%b,x,y);
    tmp=x;
    x=y;
    y=tmp-a/b*y;
    return ans; 
}
int main()
{
    ll a,b,c,k,p=1;
    while(1)
    {
        ll x,y;
        p=1;
        scanf("%lld%lld%lld%lld",&a,&b,&c,&k);
        if(a==0&&b==0&&c==0&&k==0)
        {
            break;
        }
        for(int i=1;i<=k;i++)
        {
            p*=2;
        }
        int r=extGcd(c,-p,x,y);
        if((b-a)%r!=0)
        {
            printf("FOREVER\n");
            continue;
        }
        else
        {
            p=p/r;
            p=p>0?p:-p;
            ll ans=(x*(b-a)/r%p+p)%p;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

你可能感兴趣的:(数论)