您的位置:首页 > 其它

POJ 1061 青蛙的约会(扩展欧几里得)

2015-04-25 11:50 260 查看
题目大意:

  就是说,给你两个起始的x和y,然后x每次增加m,y每次增加n,以及长度L,求出最小的变化次数T,有(x+m*T)-(y+n*T)==P*L.

解题思路:

  裸裸的扩展欧几里得。

  分析:假设跳了T次以后,青蛙1的坐标便是x+m*T,青蛙2的坐标为y+n*T。它们能够相遇的情况为(x+m*T)-(y+n*T)==P*L,其中P为某一个整数,变形一下

得到(n-m)*T+P*L==x-y 我们设a=(n-m),b=L,c=x-y,T=x,P=y.于是便得到ax+by==c。激动啊,这不就是上面一样的式子吗。

直接套用扩展欧几里得函数,得到一组解x,y。由于问题是问最少跳多少次,于是只有x是我们需要的信息。那么再想,x是最小的吗?

  答案是可能不是!那么如何得到最小解呢? 我们考虑x的所有解的式子: x=x0+b/d*t。x0是我们刚刚求到的,很显然右边是有个单调函数,当t为某一个与x正负性质相反的数时,可以得到最小的x。 令x的正负性质为正,那么x=x0-b/d*t1 (t1==-t)。令x==0,那么t=x0*d/b,最小的x等于x0减去t*b/d。这里得到的x可能是负数,如果是负数,我们再为它加上一个b/d即是所求答案了!

代码:

# include<cstdio>
# include<iostream>
# include<fstream>
# include<algorithm>
# include<functional>
# include<cstring>
# include<string>
# include<cstdlib>
# include<iomanip>
# include<numeric>
# include<cctype>
# include<cmath>
# include<ctime>
# include<queue>
# include<stack>
# include<list>
# include<set>
# include<map>

using namespace std;

const double PI=4.0*atan(1.0);

typedef long long LL;
typedef unsigned long long ULL;

# define inf 999999999

LL x,y,a,b,c,d;
LL n,m,X,Y,L;

LL ext_gcd( LL a,LL b )
{
LL t,d;
if ( b==0 )
{
x = 1;
y = 0;
return a;
}
d = ext_gcd(b,a%b);
t = x;
x = y;
y = t-(a/b)*y;
return d;
}

int main(void)
{
while (cin>>X>>Y>>m>>n>>L )
{
a = n-m;
b = L;
c = X-Y;
d = ext_gcd(a,b);
if ( c%d!=0 )
{
printf("Impossible\n");
continue;

}
x = x*(c/d);
y = y*(c/d);

LL k = x*d/b;
k = x-k*b/d;
if ( k<0 )
{
k+=b/d;
}
cout<<k<<endl;
}

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