Description
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 is finished by a line containing four zeros.
Output
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;
}