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; ...
随机推荐
- TI IPNC Web网页之进阶修改
GoDB内嵌HTML 原始的页面里面已经有一个内嵌HTML的例子了,那就是维护支持页面.下图是稍微修改后的页面...请自行脑补. 这里使用的是上一节所说的gdo containter的方法. 打开ma ...
- Corosync+pacemaker实现集群的高可用
一.Corosync和pacemaker的了解: Corosync是集群管理套件的一部分,他在传递信息的时候可以通过一个简单的配置文件来定义信息传递的方式和协议等.也就是说,corosync是Mess ...
- location.host 与 location.hostname 的区别
JavaScript 中,大多数情况下,我们不会发现 location.host 与 location.hostname 的区别,因为大多数情况下,我们的网页用的是 80 端口. 他们的区别: loc ...
- EasyRMS录播管理服务器项目实战:windows上开机自启动NodeJS服务
本文转自EasyDarwin开源团队成员Penggy的博客:http://www.jianshu.com/p/ef840505ae06 近期在EasyDarwin开源团队开发一款基于EasyDarwi ...
- yxy-插入formid-并发/压力(入参的变量化)
1.抓取接口如下 2.该接口为插入数据库操作,由于前段操作频繁,就简单压测一下 接口中formId.accountId.openId为变量 formId为随机生成插入:accountId.openId ...
- 微信小程序视频教程
微信小程序全套视频教程在线观看地址:http://v.qq.com/vplus/92e0ff1abe80fce5bcfe344f11a106c5/foldervideos/hod000101p9le1 ...
- 人生苦短之我用Python篇(XML模块)
XML模块 http://baike.baidu.com/link?url=-mBgvMdEDU7F05Pw7h_hBt7A0ctYiPm5a_WvKVLknydnRXKRIyydcVZWRjd_5H ...
- 类中的__slots__方法与__dict__方法相排斥
类的 __slots__ 列表 作用: 限定一个类创建的实例只能有固定的属性(实例变量) 不允许对象添加列表以外的属性(实例变量) 防止用户因错写属性的名称而发生程序错误 说明: 1. __slots ...
- 在mac os x 下升级emacs
大概是09年的时候接触到emacs这个编辑器,当时我们c语言老师用的,他自信满满,而那时我是个vimer,所以每次看他按那么多组合键我就替他感觉手指头累啊. 再后来我用了几年vim写代码,再后来用了许 ...
- bzoj 1858 序列操作
bzoj 1858 序列操作 带有随机多个区间单值覆盖的区间操作题,可考虑用珂朵莉树解决. #include<bits/stdc++.h> using namespace std; #de ...