ZOJ 3593 One Person Game(拓展欧几里得求最小步数)
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 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或c步,c=a+b;问最小步数;
根据公式ax+by=c;,当x,y同号时等于max(x,y),当a,b异号时等于(abs(x)+abs(y)),因为a,b大于0,所以不管x,y同号还是异号都是当x,y,最接近时,答案最小,写出通式
x=x1+b/(gcd)*k,y=y1-a/gcd*k; 假设x,y相等,k=(y-x)/(a+b),因为x,y不一定相等,所以枚举k附近的点
大意:一维坐标轴,有A和B两个地方,现在从A到B,每次可以向任意方向走a、b或者c的距离,其中c=a+b,问能不能走到B,能的话最少走几次。
首先可以推出这个式子:a*x+b*y+c*z=|B-A|然后又因为c=a+b,所以其实可以化成a*x+b*y=|B-A|。所以需要用扩展gcd求出x,y,但是这个x,y有可能不是最优的,为什么呢?为了让步数最小就要拉近x,y的距离,使|x-y|最小。怎么拉近,
下面来看通解方程:
x = x0 + (b/gcd)*t
y = y0 – (a/gcd)*t
实际上是关于x,y关于t的两条直线(他们必有交叉点)。
可以设x==y,然后解出那个对应的t
,得到此时的一组解(t=(y0-x0)/((a+b)/gcd))但是实际上有可能无法使x==y(没有整数t),所以算出来的t接近于交叉点的t(有可能是小数),所以可能也不是最优解,所以需要增加一次t+1,t-1,这样比较3个t得到的结果(x,y同为正或同为负时,绝对值大的那个值(c的存在,a和b合并为c),一正一负就是绝对值和),其中小的一个必是最优解。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm> #define INF 0x7fffffff
#define EPS 1e-12
#define MOD 100000007
#define PI 3.14159265357979823846
#define N 100005 using namespace std; typedef long long ll; ll e_gcd(ll a, ll b, ll &x, ll &y)
{
ll d = a;
if (b != )
{
d = e_gcd(b, a%b,y, x);
y = y - a / b * x;
}
else
{
x = ; y = ;
}
return d;
} ll cal(ll a, ll b, ll l)
{
ll x, y;
ll gcd = e_gcd(a, b, x, y);
if (l%gcd != ) return -;
x *= l / gcd;
y *= l / gcd;
a = a / gcd;
b = b / gcd;
ll ans = ((ll)INF)*((ll)INF), f;
//下面来看通解方程:
// x = x0 + (b / gcd)*t
// y = y0 –(a / gcd)*t
// 实际上是关于x, y关于t的两条直线(他们必有交叉点)。
// 可以设x == y,然后解出那个对应的t
// , 得到此时的一组解(t = (y0 - x0) / ((a + b) / gcd))
//但是实际上有可能无法使x == y(没有整数t)
ll mid = (y - x) / (a + b);
for (ll T = mid - ; T <= mid + ; T++)
{
// 当x, y同号时等于max(x, y),先走几步(a+b)的,再走几步单独的
if (abs(x + b * T) + abs(y - a * T) == abs(x + b * T + y - a * T))
f = max(abs(x + b * T), abs(y - a * T));
else//当a,b异号时等于(abs(x)+abs(y))
f = fabs(x - y + (a + b)*T);
ans = min(ans, f);
}
return ans;
} int main()
{
ll A, B, a, b, x, y;
int t;
cin >> t;
while (t--)
{
cin >> A >> B >> a >> b;
ll l = B - A;
ll ans = cal(a, b, l);
if (ans == -) cout << "-1"<<endl;
else cout << ans << endl;
}
return ;
}
ZOJ 3593 One Person Game(拓展欧几里得求最小步数)的更多相关文章
- ZOJ 3609 Modular Inverse(拓展欧几里得求最小逆元)
Modular Inverse Time Limit: 2 Seconds Memory Limit: 65536 KB The modular modular multiplicative ...
- gcd模板(欧几里得与扩展欧几里得、拓展欧几里得求逆元)
gcd(欧几里得算法辗转相除法): gcd ( a , b )= d : 即 d = gcd ( a , b ) = gcd ( b , a mod b ):以此式进行递归即可. 之前一直愚蠢地以为辗 ...
- ZOJ 3593.One Person Game-扩展欧几里得(exgcd)
智障了,智障了,水一水博客. 本来是个水题,但是for循环遍历那里写挫了... One Person Game Time Limit: 2 Seconds Memory Limit: 655 ...
- Modular Inverse (拓展欧几里得求逆元)
The modular modular multiplicative inverse of an integer a modulo m is an integer xsuch that a-1≡x ( ...
- ZOJ - 3593 One Person Game (扩展欧几里得)
题意:一个人在坐标A,要前往坐标B的位置.可以往左或往右走a,b,a+b个单位,求到达B的最小步数. 分析:扩展欧几里得算法求解线性方程的套路不变.令C=fabs(A-B),c = a+b, 扩展gc ...
- POJ 1061 青蛙的约会(拓展欧几里得求同余方程,解ax+by=c)
青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 122871 Accepted: 26147 Descript ...
- 拓展欧几里得求 ax + by = c的通解(a >=0, b >= 0)
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> ...
- POJ 2891 Strange Way to Express Integers(拓展欧几里得)
Description Elina is reading a book written by Rujia Liu, which introduces a strange way to express ...
- Looooops(求解同余方程、同余方程用法)【拓展欧几里得】
Looooops(点击) A Compiler Mystery: We are given a C-language style for loop of type for (variable = A; ...
随机推荐
- eureka-7-多网卡下的ip选择
目前没有需求,后面需要的话,再补充 只是简单使用的话,只需要指定ip即可 eureka.instance.ip-address:127.0.0.1
- LeetCode OJ:Add and Search Word - Data structure design(增加以及搜索单词)
Design a data structure that supports the following two operations: void addWord(word) bool search(w ...
- C# 用Mutex或进程限制一台电脑上同时打开多个实例
private void Form1_Load(object sender, EventArgs e) { bool requestInitialOwnership ...
- 208.11 RF test
1) filter (not related); 2) Crystal (in progress); 3) IC; 4) Antenna. (not related) The three most ...
- FCT test device
- Python中函数装饰器及练习
)]) ,,],)
- Redis的集群安装以及rehash重新迁移教程指南
1. Redis的cluster集群 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最核心的目标有三个: 性能:这是Redis赖以生存的看家本领,增加集群 ...
- 我也说说Emacs吧(6) - Lisp速成
前面我们学习了基本操作,也走马观花地看了不少emacs lisp的代码.这一章我们做一个lisp的速成讲座. Lisp的含义是表处理语言.它的代码组成结构都是用括号组成的表来表示的.Lisp中的功能, ...
- 使用tr1的bind函数模板
最近把公司的VS2008统一升级为SP1了,虽然还是有些跟不上时代,毕竟C++17标准都出了,但是,对于成熟的商业软件开发而言,追求更新的C++标准肯定不是正道.升级SP1的VS2008可以支持TR1 ...
- VUE 入门 01
什么是VUE? 它是构建用户界面的JavaScript框架(让他自动生成js.css.html) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vu ...