您的位置:首页 > 其它

poj1061青蛙的约会

2011-12-08 21:09 260 查看
拿到这道题之后,很快就会把它转化为 ax+by=d的求解问题(a,b,d已知,求x,y)。这个问题如何求解呢。

我一开始用穷举。很显然,会TLE.

然后,看了别人的解题方法。原来这就是传说中的扩展的欧几里得问题。

用欧几里得求两个数的最大公约数大家都会。但是这个扩展的欧几里得就不那么好理解了。

在网上找的对扩展的欧几里得的理解:

扩展欧几里德算法理解(By ruiqi)

欧几里德算法很好理解了。但是扩展了一下却一直弄的不明不白。

网上关于这个的讲解是很多了。但总体说来都不是太好理解。

思索了好长时间,总结了下面的思路:(自我感觉良好了)

扩展欧几里德定理

对于与不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数。那么存在整

数 x,y 使得 gcd(a,b)=ax+by。(貌似 x,y 也是唯一的,这个我不是太清楚的)。

最重要的是怎么理解下面的代码了:

#inc lude<iostream>

using namespace std;

int x,y,q;

void extend_Eulid(int a,int b)

{

if (b==0)

{

x=1; y=0; q=a;

}

else

{

extend_Eulid(b,a%b);

int temp=x;

x=y; y=temp-a/b*y;

}

}

int main()

{

int a,b;

cin>>a>>b;

if (a<b) swap(a,b);

extend_Eulid(a,b);

printf("%d=(%d)*%d+(%d)*%d\n",q,x,a,y,b);

}

求解 x,y 的方法的理解

我们不妨设 a>b。

1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

2,ab<>0 时

设 ax1 +by1 =gcd(a,b);

bx2 +(a%b)y2 =gcd(b,a%b);

根据朴素欧几里德原理有 gcd(a,b)=gcd(b,a%b);

则:ax 1 +by1 =bx2 +(a%b)y2 ;

即:ax 1 +by1 =bx2 +(a-(a/b)*b)y2 =ay2 +bx2 -(a/b)*by2 ;

根据恒等定理得:x1 =y2 ; y1 =x2-(a/b)*y2 ;

这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.

上面的思想是递归定义了,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以

结束。

有了这个分析,extend_Eulid 函数的理解也就不难了。

理解了欧几里得,这道题算是解了一半。然后要做的就是对普通的ax+by=d(d并不一定是gcd(a,b))求解。

详细分析过程见http://blog.csdn.net/SwordHoly/article/details/4423543

做这道题,太扯了,完全是数学啊。 数学,我的痛处。

/*
* =====================================================================================
*
*       Filename:  1061.c
*
*    Description:
*
*        Version:  1.0
*        Created:  2011年12月08日 11时27分16秒
*       Revision:  none
*       Compiler:  gcc
*
*         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com
*        Company:  Dalian University Of Technology
*
* =====================================================================================
*/

#include<stdio.h>

//please declare parameters here.
long long k,t,d;

//please declare functions here.
void extend_gcd(long long a,long long b)
{
if(b==0)
{
k=1;
t=0;
d=a;
}
else
{
extend_gcd(b,a%b);
long long temp;
temp=k;
k=t;
t=temp-(a/b)*t;
}
}
int main()
{
freopen("input.txt","r",stdin);
long long a,b;
long long int x,y,m,n,l;
//input your ...
while(scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&l)!=EOF)
{
a=m-n;
b=y-x;
if(a<0)
{
a=-a;
b=-b;
}
extend_gcd(a,l);
if(b%d!=0)
{
printf("Impossible\n");
}
else
{
k=k*b/d;
t=t*b/d;
l=l/d;
if(k>=0)
k=k%l;
else
k=k%l+l;
if(k==0)
k=l;
printf("%lld\n",k);
}
//		printf("%lld %lld %lld %lld %lld",x,y,m,n,l);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: