【扩展欧几里德算法】双六
题目描述
一个双六上面有向前向后无限延续的格子(如下图所示),每个格子都写有整数。其中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; } }
祝你早日攒够失望,然后开始新的生活。