ZOJ-3593-One Person Game-數論-擴充套件歐幾里得.md
阿新 • • 發佈:2018-12-11
【Description】
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 A, B, a and b, separated by spaces. (-2^31 ≤ A, B < 2^31, 0 < a, b < 2^31)
【Output】
For each test case, output the minimum number of steps. If it's impossible to reach point B, output "-1" instead.
【Examples】
Sample Input
2 0 1 1 2 0 1 2 4
Sample Output
1 -1
【Problem Description】
在一維座標系內,從A走到B所需要的最少步數,每次可以向任意方向走a,b,c步,其中c=a+b.
【Solution】
因為c=a+b,所以,c可以分解到a,b中,所以可以先不考慮c,最後再處理。 即此題就是求ax+by=B-A的解。 由擴充套件歐幾里得:
可求得一對特解:x0=xc/gcd(a,b),y0=yc/gcd(a,b)(這裡不懂可以先去學擴充套件歐幾里得) 則通解x=x0+b/gcd*t,y=y0-a/gcd*t,其中t為未知數。 因為題目要求最小步數,即如果x==y,那麼答案就是x。 若x!=y,且xy>0,則答案就是max(x,y); 例:2x+3y=7,解得x=2,y=1,那麼走的步數就是c+a=5+2=7,2步 否則,xy<0,則答案就是abs(x)+abs(y);例:3x+5y=7,解得x=-1,y=2,那麼走的步數就是b+b+(-a)=7,3步 所以最小步數取在x==y時,對上面通解進行求解,可解的t的值,但由於t可能不為整數解,所以對其兩邊求最小 值。
【Code】
/*
* @Author: Simon
* @Date: 2018-09-14 16:11:04
* @Last Modified by: Simon
* @Last Modified time: 2018-09-14 16:32:55
*/
#include<bits/stdc++.h>
using namespace std;
typedef int Int;
#define int long long
#define INF 0x3f3f3f3f
#define maxn 100005
int exgcd(int a,int b,int &x,int &y)//擴充套件歐幾里得
{
if(b==0)
{
x=1,y=0;
return a;
}
int ans=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return ans;
}
void solve(int a,int b,int c)
{
int x,y;
int gcd=exgcd(a,b,x,y);
if(c%gcd!=0)
{
cout<<-1<<endl;
return ;
}
x*=c/gcd,y*=c/gcd;//ax+by=gcd(a,b)---->ax*(c/gcd(a,b))+by*(c/gcd(a,b))=c,x,y為一個特解
a/=gcd,b/=gcd;//為求通解x=x0+b/gcd*t,y=y0-a/gcd*t,做準備
int mid=(y-x)/(a+b),ans=1e18;//當x==y時,求得t的值
for(int i=mid-1;i<=mid+1;i++)//查詢最終答案
{
int tmp=0;
if(abs(x+b*i)+abs(y-a*i)==abs(x+b*i+y-a*i)) tmp=max(abs(x+b*i),abs(y-a*i)); //同方向
else tmp=abs(x+b*i)+abs(y-a*i);//不同方向
ans=min(ans,tmp);
}
cout<<ans<<endl;
}
Int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int A,B,a,b;
cin>>A>>B>>a>>b;
int c=abs(B-A);
solve(a,b,c);
}
cin.get(),cin.get();
return 0;
}