【扩展欧几里德算法】双六

题目描述

一个双六上面有向前向后无限延续的格子(如下图所示),每个格子都写有整数。其中0号格子是起点,1 号格子是终点。而骰子上只有a,b,-a,-b四个整数,所以根据a和b的值的不同,有可能无法到达终点。现在的问题是掷出a,b,-a,-b各多少次可以达到终点呢?(双六是类似大富翁的一款桌上游戏,不懂也没关系的啦)

输入

一行,包含两个数 a 和 b,两数之间用一个空格分隔,含义如题目所述。

输出

一个数,表示掷出四个整数次数的和,如果解不唯一,就输出和最小的值,如果无解则输出 0 。

样例输入

4 11

样例输出

4

 

说明

 数据范围:1≤a,b≤10的9次方。

样例解释:掷出a为3次,b为0次,-a为0次,-b为1次, 3*a-l*b=l。

 

 分析

列个方程,ax1+(-a)x2+bx3+(-b)x4=1,即a(x1-x2)+b(x3-x4)=1,设x1-x2为x,x3-x4为y,则原式=ax+by=1为不定方程,所以用扩展欧几里德算法来求。因为a和-a,b和-b是相互抵消的,所以x取绝对值就是a和-a最小的移动的步数,y同理。

 

参考代码

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int extgcd(int a,int b,int& x,int& y);
int main()
{
    int a,b;
    int x,y;
    scanf("%d%d",&a,&b);
    if(a<b){
        swap(a,b);
    }

   if(extgcd(a,b,x,y)==1){
    if(x<0)x=-x;
    if(y<0)y=-y;
    printf("%d\n",x+y);
   }
   else
    printf("0\n");

    return 0;
}
int extgcd(int a,int b,int& x,int& y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    else{
    int t=extgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return t;
    }

}

 

posted @ 2017-08-29 08:58  路人姜。  阅读(228)  评论(0编辑  收藏  举报