http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=630
description |
Raven likes games of numbers. Today he meets two numbers and thinks whether he could get a result of 1 by doing at least one operation (addition or subtraction). However, he is tired of calculation; he also wants to know the minimum steps of operation that he could get 1.
|
input |
The first line of the input contains an integer T, which indicates the number of test cases. In the following T rows, there are two positive integers a, b ( 0<=a, b<=10^9) in each row. |
output |
For each case, output the least number of steps. If you cannot get 1, just output -1. |
sample_input |
Sample Input 3 3 2 16 9 6 8 |
sample_output |
1 10 -1 |
hint |
Sample 1: 3 - 2 = 1, One subtraction will be needed. Sample 2: 16-9+16-9+16-9-9-9+16-9-9=1,It requires 10 additions and subtractions. Sample 3: You cannot get 1. |
若要满足题的要求:gcd(a,b)是1的因数就行,因此只能是1,故此,首先两个数要互素。。。
扩展欧几里得算法得出的是使得式子:a*x+b*y==gcd(a,b)成立的式子的特解:x1,y1,满足:x=x1+t*b,y=y1+t*b,且|x1|<a,|y1|<b。因此题目要求的是|x1|+|y1|最小,故此:当x1<0时比较|x1+b|+|y1-a|和x1,y1 的大小取小的,当x1>0时,比较|x1-b|+|y1+a|和x1,y1 的大小取小的。另外对a==1时做特殊考虑。说到这里可一看代码了.
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> using namespace std; typedef long long LL; LL gcd(LL a,LL b) { return b ? gcd(b,a%b):a; } void extend_Euclid(LL a,LL b,LL &x,LL & y) { if(b == 0) { x = 1; y = 0; return; } extend_Euclid(b,a%b,x,y); LL tmp = x; x = y; y = tmp - (a / b) * y; } int main() { int T; cin>>T; while(T--) { LL a,b; cin>>a>>b; if(a < b) swap(a,b); LL g = gcd(a,b); if(g != 1) { puts("-1"); continue; } if(b == 1 && a == 2) { puts("1"); continue; } if(b == 1) { puts("2"); continue; } if(b == 0 && a != 1) { puts("-1"); continue; } if(b == 0 && a == 1) { puts("1"); continue; } LL x,y; extend_Euclid(a,b,x,y); LL ans = abs(x) + abs(y); if(x < 0) { LL tmp = abs(x + b) + abs(y-a); if(tmp < ans) ans = tmp; } else { LL tmp = abs(x - b) + abs(y + a); if(tmp < ans) ans = tmp; } cout<<ans-1<<endl; } return 0; }