首页 > 代码库 > POJ 2115 C Loooooops 扩展欧几里得

POJ 2115 C Loooooops 扩展欧几里得

http://poj.org/problem?id=2115

题意:给出a,b,c<=1e9,k<=32 求出p 使得 (a+pc)mod2^k=b
a+pc同余b(mod2^k) 2^kx=a+pc-b -> 2^kx-pc=a-b 利用exgcd求出x,p即可

最小正整数解
x=x0+(k/d)*n 通解 任意解:x同余x0 mod(k/d)

x0%(k/d)显然和x0同余(k/d)
x=(x0%k/d+k/d)%mod 为最小正整数解

x0%k/d为正 x显然为最小正整数解

x0%k/d为负,x0%k/d+k/d显然与x0同余k/d 也为正数 所以为最小正整数解

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=2e5+20;
ll a,b,c,k;
ll x,y;
ll exgcd(ll a,ll b)
{
	ll d;
	if(b==0)
	{
		y=0,x=1;
		return a;
	}
	
	d=exgcd(b,a%b);
	ll t=y;
	y=x-a/b*y;
	x=t;
	return d;
	
} 
int main()
{
	while(cin>>a>>b>>c>>k&&(a+b+c+k))
	{
		k=(ll)1ll<<k;
		ll d=exgcd(c,k);
		if((b-a)%d||(a!=b&&c==0))
			puts("FOREVER");
		else
		{
			//
			x=x*(b-a)/d;
			//x=x0+(k/d)*n 通解  任意解 x同余x0 mod(k/d) 
			
			//x0%(k/d)显然和x0同余(k/d)
			//现在要使x为最小正整数解 如果x0%k/d可能为正或者负 所以x=(x0%k/d+k/d)%mod 为最小正整数解   
			ll t=k/d;
			x=(x%t+t)%t; //最小正整数解  
			cout<<x<<endl;
		}
	}
	return 0;
}

  

 

POJ 2115 C Loooooops 扩展欧几里得