1. 程式人生 > >POJ C Looooops

POJ C Looooops

a*x和b同餘N時,當b為gcd(a,N)的倍數時有整數解,設x0 = ex_gcd(a,N,b),可得符合條件的x的集合為:x0+k*n'(n' = N / gcd(a,N));

題目很簡單,其實就是用尤拉定理求一下逆元即可,注意求出的逆元可能不是最小正整數。需要用公式求一下最小正整數即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll __int64

using namespace std;

ll N;

void ex_gcd(ll a, ll b, ll&d, ll& x, ll& y){      
    if (b == 0){  
        d = a;  
        x = 1;  
        y = 0;  
        return;  
    }  
    ex_gcd(b,a%b,d,y,x);  
    y -= (a/b)*x;  
}  

ll gcd;
bool mark; 
   
ll modular(ll a, ll b){  
    ll x, y, d;  
    ex_gcd(a,N,d,x,y);
	gcd = d;  
    if (b % d == 0){  
        x = (x* (b/d)) % N ;       
        x = (x + N) % (N/d);
		mark = true;         
        return x;   
    }  
    return -N;  
}  

int main(){
	ll a,b,c,k;
	while (scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&k) && !(a==0 && b==0 && c==0 && k==0)){
		N = (1LL<<k);
		b = (b-a+N ) % N;
		mark = false;
		ll ans = modular(c,b);
		if (!mark){
			printf("FOREVER\n");
		}
		else{
			ll t = N / gcd;
			if (ans < 0){
				ans = ans + t*((ans / t) + (ans % t == 0 ? 0 : 1));
			}
			if (ans -t > 0){
				ans = ans - t*(ans / t);
			}
			printf("%I64d\n",(ans+N) % N);
		}
	}
	return 0;
}