zoukankan      html  css  js  c++  java
  • Gym100812 L 扩展欧几里得

    L. Knights without Fear and Reproach
    time limit per test
    2.0 s
    memory limit per test
    256 MB
    input
    standard input
    output
    standard output

    They were all dead. The final lunge was an exclamation mark to everything that had led to this point. I wiped my sword from the blood of Dragon and sheathed it. And then it was all over. Devastated, I came out of the empty castle and wandered somewhere along a dirt road. But before I could think about what I would do now, I heard a piercing scream from behind: "Stop right now! Drop a sword and raise your hands up!". They were knights. Only knights scream like that before making a hit. If they had been bandits I would be already dead.

    I turned back and saw two figures in heavy armor rushing towards me. They were Lancelot and Percival — two knights of the Round Table, known for their fast reprisal over renegades like me. In the Kingdom they were called the Cleaners. As for me, not the most suitable name: they usually left a lot of dirt.

    I almost instantly read their technique. Each of them was preparing for some time, then hit instantly, then was preparing again for the same time, then hit again, and so on, while their victim was not fallen. Lancelot spent n seconds to prepare, and Percival — m seconds. I was too tired and could parry a hit only if the previous one was done more than a second ago, and there were no powers to counter-attack at all. It was the sense that Lady Luck was really a hooker, and you were fresh out of cash. The knights knew their job and the first hit I wouldn't be able to parry would finish me off. My story wouldn't have a happy end.

    Input

    The only line contains two integers separated by a space: n and m (1 ≤ n, m ≤ 2·109) — the intervals of time in seconds between hits of Lancelot and Percival correspondingly.

    Output

    Output a single integer — the number of seconds from the beginning of the fight when the protagonist will be killed.

    Examples
    input
    Copy
    9 6
    output
    18
    input
    Copy
    7 11
    output
    22

    题意 两个人分别隔 n 和 m 秒砍一刀 主角每闪避一次攻击需要休息一秒 问主角在第几秒被砍死

    解析 根据题意我们可以得到 |x*n-m*y|<=1
    一共两组情况
    第一种 |x*n-m*y|=0 x*n=m*y 最优解就是n和m的最小公倍数=n*m/gcd(n,m)
    第二种
    |x*n-m*y|=1 我们令 r = |x*n - m*y| 可以推出 r=gcd(n,m)*|(x*n/gcd(n,m)-(y*m/gcd(n,m)|=gcd(n,m)*k
    所以差值r肯定是gcd(n,m)的倍数 当最大公约数不是1的时候第二种情况不存在
    当最大公约数为1时 之前的方程|x*n-m*y|=1(x,y为正整数)可以转化为 n*x+m*y=1 (扩展欧几里得)
    跑一边 扩展欧几里得算法 可以得出一组解(x0,y0)
    
    

    我错认为最优解就是max(abs(n*x0),abs(y0*m))
    交上去居然过了 可能数据比较水 有人模拟也过了。。。(想不通)


    但是后来我又仔细想了想 扩展欧几里得算法 得出来的只是一组解 怎么能确定最优解是
    max(abs(n*x0),abs(y0*m))?
    难道就没有比他们更小的解吗?然后就想到最优解应该是|x*n|或者|m*y|越小越好 n>0,m>0所以|x|或|y|越小越好
    因为 他们相差1 所以单独考虑一个x就好了 查阅资料得到了x的通项公式x=x0+k*m/gcd(n,m)
    当x>0是 最小正整数解为 x%m 但并不能保证是绝对值最小的解 如果x%m<=m/2 x*n是最优解 反之(x-m)*n+1是最优解
    当x<0时 最小负整数解为(x+m)%m 同理

    我们再换个角度想 n*x+m*y=1
    说明 n*x>0,m*y<0 或者 n*x<0,m*y>0
    所以我们只需要求x的最小正整数解x' 和y的最小正整数解y'
    相关博客
    http://blog.csdn.net/zhjchengfeng5/article/details/7786595
    最优解就是min(x'*n,y'*m)
    而不用像上面所说的 去找x绝对值最小的解

    思维一点一点的进步。。这应该是标准答案了吧。。。
    AC代码1
     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <map>
    11 #include <vector>
    12 using namespace std;
    13 const int maxn = 6000+10;
    14 const int maxm = 1e4+10;
    15 const int inf = 0x3f3f3f3f;
    16 const int mod = 998244353;
    17 const double epx = 1e-10;
    18 typedef long long ll;
    19 const ll INF = 1e18;
    20 ll n,m,t;
    21 ll exgcd(ll a,ll b,ll &x,ll &y)   //&引用符号,修改x,y,函数返回的是a,b的最大公约数
    22 {
    23     if(b==0)
    24     {
    25         x=1;
    26         y=0;
    27         return a;
    28     }
    29     ll r=exgcd(b,a%b,x,y);            //递归下去
    30     ll temp=x;
    31     x=y;
    32     y=temp-a/b*y;
    33     return r;
    34 }
    35 int main()
    36 {
    37     cin>>n>>m;
    38     ll x,y;
    39     ll g=exgcd(n,m,x,y);
    40     ll ans=n*m/g;
    41     if(n==1||m==1)
    42     {
    43         if(n==m)
    44             cout<<"1"<<endl;
    45         else
    46             cout<<"2"<<endl;
    47         return 0;
    48     }
    49     if(g==1)
    50             ans=min(ans,max(abs(x*n),abs(y*m)));
    51     cout<<ans<<endl;
    52 }

    AC代码2

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <map>
    11 #include <vector>
    12 using namespace std;
    13 const int maxn = 6000+10;
    14 const int maxm = 1e4+10;
    15 const int inf = 0x3f3f3f3f;
    16 const int mod = 998244353;
    17 const double epx = 1e-10;
    18 typedef long long ll;
    19 const ll INF = 1e18;
    20 ll n,m,t;
    21 ll exgcd(ll a,ll b,ll &x,ll &y)   //&引用符号,修改x,y,函数返回的是a,b的最大公约数
    22 {
    23     if(b==0)
    24     {
    25         x=1;
    26         y=0;
    27         return a;
    28     }
    29     ll r=exgcd(b,a%b,x,y);            //递归下去
    30     ll temp=x;
    31     x=y;
    32     y=temp-a/b*y;
    33     return r;
    34 }
    35 ll abss(ll a)
    36 {
    37     if(a<0)
    38         return -a;
    39     else
    40         return a;
    41 }
    42 int main()
    43 {
    44     cin>>n>>m;
    45     ll x,y;
    46     ll g=exgcd(n,m,x,y);
    47     ll ans=n*m/g;
    48     if(n==1||m==1)
    49     {
    50         if(n==m)
    51             cout<<"1"<<endl;
    52         else
    53             cout<<"2"<<endl;
    54         return 0;
    55     }
    56     if(g==1)
    57     {
    58         if(x>0)
    59         {
    60             x=x%m;
    61             if(x>m/2)
    62             {
    63                 x-=m;
    64                 ans=min(ans,abss(x*n)+1);
    65             }
    66             else
    67                 ans=min(ans,x*n);
    68         }
    69         else if(x<0)
    70         {
    71             x=x%m;
    72             if(abss(x)>m/2)
    73             {
    74                 x+=m;
    75                 ans=min(ans,x*n);
    76             }
    77             else
    78                 ans=min(ans,abss(x*n)+1);
    79         }
    80     }
    81     cout<<ans<<endl;
    82 }

    AC代码3(最完美)

     1 #include <stdio.h>
     2 #include <math.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <map>
    11 #include <vector>
    12 using namespace std;
    13 const int maxn = 6000+10;
    14 const int maxm = 1e4+10;
    15 const int inf = 0x3f3f3f3f;
    16 const int mod = 998244353;
    17 const double epx = 1e-10;
    18 typedef long long ll;
    19 const ll INF = 1e18;
    20 ll n,m,t;
    21 ll exgcd(ll a,ll b,ll &x,ll &y)   //&引用符号,修改x,y,函数返回的是a,b的最大公约数
    22 {
    23     if(b==0)
    24     {
    25         x=1;
    26         y=0;
    27         return a;
    28     }
    29     ll r=exgcd(b,a%b,x,y);            //递归下去
    30     ll temp=x;
    31     x=y;
    32     y=temp-a/b*y;
    33     return r;
    34 }
    35 int main()
    36 {
    37     cin>>n>>m;
    38     ll x,y;
    39     ll g=exgcd(n,m,x,y);
    40     ll ans=n*m/g;
    41     if(n==1||m==1)
    42     {
    43         if(n==m)
    44             cout<<"1"<<endl;
    45         else
    46             cout<<"2"<<endl;
    47         return 0;
    48     }
    49     if(g==1)
    50     {
    51         ll ans1=((x%m+m)%m)*n;
    52         ll ans2=((y%n+n)%n)*m;
    53         ans=min(ans,min(ans1,ans2));
    54     }
    55     cout<<ans<<endl;
    56 }

    一开始没看题意看样例认为只是单纯的输出最大值的二倍,读一遍题暴力模拟了一发,超时了。

    为什么人家的模拟就过了。。应该超时的啊 只能说数据水了

    引发了这么长的血案。。

     
  • 相关阅读:
    记录一下idea自动生成Entity
    Spring-boot之 swagger2
    Spring-boot之 rabbitmq
    Js 跳出两级循环的方法
    Activiti 工作流变量的修改方法
    Spring-boot(二)yml文件的使用
    Spring-boot初始化创建(一)
    数据库性能优化:程序操作优化
    数据库性能优化:数据库表优化
    数据库性能优化:数据库自身优化
  • 原文地址:https://www.cnblogs.com/stranger-/p/8560892.html
Copyright © 2011-2022 走看看