NEFU 630 数论扩展欧几里得算法的应用

来源:互联网 发布:乐视员工获刑4年 知乎 编辑:程序博客网 时间:2024/06/05 06:19

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 Input33 216 96 8

sample_output

110-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.
神算法啊!!!!!!!http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

若要满足题的要求: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;}



0 0