【扩展欧几里得】BZOJ1477-青蛙的约会

一直在WA,后来我发现我把东西看反了……

【题目大意】

给出一个长度为L的环状坐标轴,两个点开始时位于(X,0)、(Y,0)。每次两点分别往右边移动m和n,问能否相遇?

【思路】

由题意,可得:

X+mt=Y+nt(mod L)

(X+mt)-(Y+nt)=L*k

(n-m)t+L*k=X-Y。

可以用扩展欧几里得来做。具体来说,显然要满足n-m和L的最大公约数(记为d)要整除X-Y,否则无解。这个可以在扩展欧几里得中求出。

式子可以化简为:[(n-m)/d]*t+(L/d)*k=(X-Y)/d。因此通解为 t'=t0+(L/d)*n(n∈Z)

由于扩展欧几里得杰出的结果其实是(n-m)*t+L*k=d的解,因此要乘以(X-Y)/d才是答案。然后往上加得到第一个大于0的解即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 ll extgcd(ll a,ll b,ll &x,ll &y)
 9 {
10     ll ret;
11     if (b==0)
12     {
13         x=1,y=0;
14         return a;
15     }
16     ret=extgcd(b,a%b,x,y);
17     ll tmp=x;
18     x=y;
19     y=tmp-(a/b)*y;
20     return ret;
21 }
22 
23 int main()
24 {
25     ll X,Y,m,n,L,x,y;
26     scanf("%lld%lld%lld%lld%lld",&X,&Y,&m,&n,&L);
27     ll d=extgcd(n-m,L,x,y);
28     if ((X-Y)%d!=0) puts("Impossible");else
29     { 
30         ll delta=abs(L/d);
31         x=(x*(X-Y)/d+delta)%delta;
32         while (x<0) x=(x+delta)%delta;
33         printf("%lld",x);
34 
35     }
36     return 0;
37 } 

 

posted @ 2016-11-13 21:29  iiyiyi  阅读(209)  评论(0编辑  收藏  举报