zoukankan      html  css  js  c++  java
  • ZOJ 3593.One Person Game-扩展欧几里得(exgcd)

    智障了,智障了,水一水博客。

    本来是个水题,但是for循环遍历那里写挫了。。。

    One Person Game

    Time Limit: 2 Seconds      Memory Limit: 65536 KB

    There is an interesting and simple one person game. Suppose there is a number axis under your feet. You are at point A at first and your aim is point B. There are 6 kinds of operations you can perform in one step. That is to go left or right by a,b and c, here c always equals to a+b.

    You must arrive B as soon as possible. Please calculate the minimum number of steps.

    Input

    There are multiple test cases. The first line of input is an integer T(0 < T ≤ 1000) indicates the number of test cases. Then T test cases follow. Each test case is represented by a line containing four integers 4 integers ABa and b, separated by spaces. (-231 ≤ AB < 231, 0 < ab < 231)

    Output

    For each test case, output the minimum number of steps. If it's impossible to reach point B, output "-1" instead.

    Sample Input

    2
    0 1 1 2
    0 1 2 4
    

    Sample Output

    1
    -1

     

    一开始没看懂题,后来懂了,c=a+b,所以就有3个方程,分别是a*x+b*y=r,a*x+c*y=r,b*x+c*y=r;

    扩展欧几里得求出来gcd之后,通过判断r是不是gcd的倍数得到方程有没有解,然后 go on。。。

    因为扩展欧几里得求出来的x和y并不是最优解,所以通过x和y的通式,x=x0+b/gcd*k;y=y0-a/gcd*k;(k为倍数)

    本来自己想的是最优解和求出来的一般解应该差不了多少,就直接从-100到100遍历的,结果发现一直wa,学长说要找方程所在直线与源点距离最近的才是结果。

    就是确定一下for的范围,不是瞎想的-100到100就以为能水过去。。。

    首先x=x0+b/gcd*k,求出来k的范围,就是[-x0*gcd/b-1,-x0*gcd/b+1],在这个范围内for一遍,然后再通过y的通解,求出来的k的范围再for一遍就得到最优解了。

    我智障,算y的k的时候,应该/a,我写成/b了_(:з」∠)_ 

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #include<stack>
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn=1e5+10;
    13 const int inf=0x3f3f3f3f;
    14 const int eps=1e-6;
    15 
    16 ll exgcd(ll a,ll b,ll &x,ll &y){
    17     if(b==0){
    18         x=1;y=0;
    19         return a;
    20     }
    21     ll r=exgcd(b,a%b,x,y);
    22     ll t=y;
    23     y=x-(a/b)*y;
    24     x=t;
    25     return r;
    26 }
    27 
    28 ll fun(ll a,ll b,ll r){
    29     ll x,y;
    30     ll gcd=exgcd(a,b,x,y);
    31     if(r%gcd!=0)return -1;
    32     else{
    33         x*=r/gcd;
    34         y*=r/gcd;
    35         ll k1=-1.0*x*gcd/b-1,k2=-1.0*x*gcd/b+1;
    36         ll kk1=1.0*y*gcd/a-1,kk2=1.0*y*gcd/a+1;//y是除以a,智障了,写成除以b了。
    37         ll ans=fabs(x)+fabs(y);
    38         for(ll i=k1;i<=k2;i++){
    39             if(fabs(x+i*b/gcd)+fabs(y-i*a/gcd)<ans)
    40                 ans=fabs(x+i*b/gcd)+fabs(y-i*a/gcd);
    41 
    42         }
    43         for(ll i=kk1;i<=kk2;i++){
    44              if(fabs(x+i*b/gcd)+fabs(y-i*a/gcd)<ans)
    45                 ans=fabs(x+i*b/gcd)+fabs(y-i*a/gcd);
    46 
    47         }
    48         return ans;
    49 
    50     }
    51 }
    52 
    53 int main(){
    54     int t;
    55     cin>>t;
    56     while(t--){
    57         ll A,B,a,b,c;
    58         cin>>A>>B>>a>>b;
    59         c=a+b;
    60         ll r=fabs(A-B);
    61         ll h1=fun(a,b,r);
    62         ll h2=fun(a,c,r);
    63         ll h3=fun(b,c,r);
    64         if(h1==-1&&h2==-1&&h3==-1)cout<<"-1"<<endl;
    65         else{
    66             ll ans=min(h1,h2);
    67             ans=min(ans,h3);
    68             cout<<ans<<endl;
    69         }
    70     }
    71 }

    水一水,溜了,慢慢补。去看主席树了。。。

  • 相关阅读:
    分布式系统(Distributed System)资料
    (转)hive基本操作
    c# 如何通过反射 获取设置属性值、
    安卓webview下使用zepto的swipe失效
    js获取本月、三个月、今年的日期插件dateHelp
    jquery获取form表单内容以及绑定数据到form表单
    JQuery阻止事件冒泡
    javascript-Cookie的应用
    chrome浏览器调试
    JavaScript设计模式之命令模式
  • 原文地址:https://www.cnblogs.com/ZERO-/p/8963909.html
Copyright © 2011-2022 走看看