POJ 1061 扩展欧几里得

假若相遇,则存在  x+ms≡y+ns(mod l)

=>(x+ms)-(y+ns)=kl;

=>x-y-(n-m)s=kl;(已知x,y,n,m,l)

=>kl+(n-m)s=x-y;

即求满足  kl+bs=a(已知 l,b,a)最小的s;

——————————

扩展欧几里德算法-求解不定方程,线性同余方程:
解不定方程ax  +  by  =  n的步骤如下:  
 
(1)计算gcd(a,  b).  若gcd(a,  b)不能整除n,则方程无整数解;否则,在方程的两边同除以gcd(a,  b),
   得到新的不定方程a'x  +  b'y  =  n',此时gcd(a',  b')  =  1  
 
(2)求出不定方程a'x  +  b'y  =  1的一组整数解x0,  y0,则n'x0,n'y0是方程a'x  +  b'y  =  n'的一组整数解。  
 
(3)根据&$#@定理,可得方程a'x  +  b'y  =  n'的所有整数解为:  
    x  =  n'x0  +  b't  
    y  =  n'y0  -  a't  
   (t为整数)  
这也就是方程ax  +  by  =  n的所有整数解  
 
利用扩展的欧几里德算法,计算gcd(a,  b)和满足d  =  gcd(a,  b)  =  ax0  +  by0的x0和y0,
也就是求出了满足a'x0  +  b'y0  =  1的一组整数解。因此可得:  
x  =  n/d  *  x0  +  b/d  *  t  
y  =  n/d  *  y0  -  a/d  *  t  
(t是整数)   

——————————

注意扩展欧几里得求解的是a'x+b'y=1的x,y的解,其中a',b'是a/gcd(a,b),b/gcd(a,b)   a,b为你输入的两个数。

例如你输入3,5和输入6,10一样x=2,y=-1,只是返回的gcd不一样而已。

#include"stdio.h"
__int64 gcd(__int64 a,__int64 b)
{
	return b?gcd(b,a%b):a;
}
void egcd(__int64 a,__int64 b,__int64 &x,__int64 &y)//已求出gcd,故不需要返回
{
	__int64 tmp,i;
	if(!b)
	{
		x=1;y=0;
		return ;
	}
	else{
	egcd(b,a%b,x,y);
	tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	}
	return ;
}
int main()
{
	__int64 x,y,m,n,l;
	__int64 a,b,d,k,s,t;
	while(scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&l)!=EOF)
	{
	a=n-m;
	b=l;
	d=x-y;
	__int64 r=gcd(a,b);
	if(d%r)
	{
		printf("Impossible\n");

	}
	else 
	{
		a/=r;
		b/=r;
		d/=r;
		egcd(a,b,s,k);
		s*=d;
		k*=d;
		t=s/b;
		s-=t*b;
		if(s<0)
			s+=b;
		printf("%I64d\n",s);
	}
	}
	return 0;
}
posted @ 2011-05-10 20:06  Ac_smile  阅读(264)  评论(0编辑  收藏  举报