POJ 2115 C Looooops(擴展歐幾里得)

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. 

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,循環終止值b和增量c,問在k位存儲體系中循環多少次可以終止,也就是轉化成了求出cx+2^ky=(b-a)的一組可行解,根據擴展歐幾里得,如果(b-a)不可以被gcd(c,2^k)整除,那麼該方程無解,輸出“FOREVER”,可以整除則至少存在一組可行解,擴展歐幾里得算法便求出了其中一解。

根據這題題意,對於循環次數x,x=[(B-A+2^k)%2^k] /C

即 Cx=(B-A)(mod 2^k)  此方程爲模線性方程,本題就是求x的值。
即求模線性方程 ax=b( mod n)的解。 其中a=C,b=B-A,n=2^K.
該方程有解的充要條件爲b% gcd(a,n)==0
令d=gcd(a,n)有該方程的 最小整數解爲 x0 = X mod (n/d)
X爲任意解,x0爲最小整數解

這題唯一需要注意的就是k=32時int會溢出,所以要用long long 纔可以。


#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#include <ctime>

#define STD_REOPEN() freopen("../in.in","r",stdin)
#define STREAM_REOPEN fstream cin("../in.in")
#define INF 0x3f3f3f3f
#define _INF 63
#define eps 1e-4
#define MAX_V 100010
#define MAX_P 2010
#define MAX_E 4001000
#define MAX 32000
#define MOD_P 3221225473

using namespace std;

long long extendGCD(long long a,long long b,long long &x,long long &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	long long ans=extendGCD(b,a%b,x,y);
	long long t=x;
	x=y;
	y=t-a/b*y;
	return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    long long a,b,c,k,x,y;
    while(cin>>a>>b>>c>>k,a||b||c||k)
    {
		long long d=1;
		d<<=k;
		//cout<<d<<endl;
		long long e=extendGCD(c,d,x,y);
		if((b-a)%e)
			cout<<"FOREVER"<<endl;
		else
		{
			long long t=d/e;
			x=(x*(b-a)/e%t+t)%t;
			cout<<x<<endl;
		}
    }

    return 0;
}


發佈了104 篇原創文章 · 獲贊 28 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章