zoj3593One Person Game (扩展欧几里德)
2016-02-28 21:20
337 查看
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 6kinds 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 testcase is represented by a line containing four integers 4 integers A, B, a and b, separated by spaces. (-231 ≤ A, B < 231, 0 < a, b < 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
题意:有两个端点A,B,每次你可以向左或者向右走a,b,a+b的距离,问最少走多少次能从A走到B。
思路:设A,B之间的距离为dis,a+b=c,那么题目等价于min{|x|+|y| | (ax+by=dis) || (ax+cy=dis) || (bx+cy=dis) }.注:扩展欧几里德算出来ax+by=gcd(c,d)中的特殊值x,y一定满足|x|+|y|最小,但是如果算的是ax+by=d,(d%gcd(a,b),但是d!=gcd(a,b))那么就不一定|x|+|y|最小,此时要使得x趋近于0,或者使得y趋近于0,这样算出来的k带入然后取几者中的最小值,因为x,y的关系式是一条直线,|x|+|y|=m在直线接近坐标轴的情况下取到最小值。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<string>#include<algorithm>using namespace std;typedef long long ll;typedef long double ldb;#define inf 10000000000000LL#define pi acos(-1.0)#define MOD 1000000007#define maxn 1000005ll extend_gcd(ll a,ll b,ll &x,ll &y){if(b==0){x=1;y=0;return a;}ll d=extend_gcd(b,a%b,y,x);y-=a/b*x;return d;}ll niyuan(ll a,ll n){ll x,y;ll d=extend_gcd(a,n,x,y);if(d==1) return (x%n+n)%n;else return -1;}ll gcd(ll a,ll b){return (b>0)?gcd(b,a%b):a;}ll solve(ll a,ll b,ll dis){ll x,y,d,x0,y0,ans;d=extend_gcd(a,b,x,y);if(dis%d!=0)return -1;x0=x*dis/d;y0=y*dis/d;ll aa,bb;aa=a/d;bb=b/d;ll k;k=-x0/bb-1;ans=abs(x0+bb*k)+abs(y0-aa*k);k++;ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );k++;ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );k=y0/aa-1;ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );k++;ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );k++;ans=min(ans,abs(x0+bb*k)+abs(y0-aa*k) );return ans;}int main(){int n,m,i,j,T;ll x1,x2,a,b,c,x,y;scanf("%d",&T);while(T--){scanf("%lld%lld%lld%lld",&x1,&x2,&a,&b);ll dis=abs(x2-x1);c=a+b;ll ans=solve(a,b,dis);ans=min(ans,solve(a,c,dis));ans=min(ans,solve(b,c,dis));printf("%lld\n",ans);}return 0;}
相关文章推荐
- [Android]使用HorizontalScrollView实现广告栏Banner及相关原理分析
- JavaScript 正则表达式
- WM_PAINT详解
- SPARK排序算法,使用Scala开发 二次排序 自定义KEY值,相比JAVA的罗嗦,Scala优雅简洁!!!
- BSTR、char*和CString转换
- HDOJ 1412 {A} + {B}
- 二级指针
- 2.3 写入AVI视频文件
- LNMP环境搭建
- UVA12563 Jin Ge Jin Qu hao(背包问题)
- Data Structures And Problem Solving Using Java (Fourth Edition)中译版(Java 修饰词与可见性)
- ionic css布局之bar页眉页脚定义
- 计算机网络学习笔记----互联网分层及协议
- POJ 3122 pie 二分
- 5.1数组(一维部分)
- const形参与非const形参
- CSS——div居中,window.open(0
- HTML窗体指南
- Java自定义比较器实现中文排序
- 【SSME】java.lang.IllegalStateException: Failed to load ApplicationContext