zoukankan      html  css  js  c++  java
  • 【扩展欧几里得】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 } 
  • 相关阅读:
    设计模式之观察者模式
    设计模式之建造者模式
    设计模式之外观模式
    设计模式之模板方法模式
    设计模式之原型模式
    自己动手写计算器v1.1
    自己动手写计算器v1.0
    Guid的使用
    设计模式学习---代理类
    StringBuilder的使用
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6059950.html
Copyright © 2011-2022 走看看