woj 1206 QQ军旗

woj1206 - QQ军旗

Time Limit: 1000MS   Memory Limit: 65536KB   Difficulty: 5   Total Submit: 1902  Accepted: 391  Special Judge: No

Description: mmd最近喜欢上了玩QQ军棋,QQ军旗分为四人对战和两人对战。其中四人对战赢输对应得失a个QQ游戏币,两人对战输赢对应得失b个QQ游戏币。小金鱼的妈妈想让小金鱼跟mmd学习玩军棋,于是安排小金鱼每天去mmd家观战。但是小金鱼喜欢的是dota,所以他经常假借去学棋而实际去玩dota。金鱼妈想到一个办法一定程度上能发现小金鱼是否欺骗她,就是让小金鱼每次去学棋时记住mmd的QQ游戏币总数n并且回来汇报。由于有些n是不可能出现的,所以当出现不可能出现的n,金鱼妈就可以判断出小金鱼欺骗了她。你的任务是写一个程序判断出这个n是否可能出现。

Input: 多组数据,每个数据一行,每行三个数a,b,n(a,b非负且小于2^31,n为-2^31-2^31-1)。

Output: 若n为可能的输出Possible!否则Impossible!

Sample Input: 2 3 5

Sample Output: Possible!

======================================================================================================================================

这种问题,可以归类为:判断 齐次方程 是否有整数解问题,就是 ax+by = c 是否能找到整数值的 x,y 解的问题。

好吧,如果你这样想下去你就跪了 …… 其实应该这么想,因为是整数解范围的问题,就是将 c 分解为很多组成部分,这些组成部分可以由 a, b 随机分布组成。节奏对了 …… 接下来想想看,不管怎么组合,其实 c 都是由 a,b 中的最大公约数组合起来的。OK!就是这样,判断 c 能否由 a,b 的最大公约数整除。问题现在变为:求解 a,b 的最大公约数

最原始最有效的方法是“辗转相除法”(欧几里得算法),算法如下:

辗转相除法是利用以下性质来确定两个正整数 a 和 b 的最大公约数的:
1. 若 r 是 a ÷ b 的余数, 则
gcd(a,b) = gcd(b,r)
2. a 和其倍数之最大公约数为 a。
另一种写法是:
1. a ÷ b,令r为所得余数(0≤r<b)
若 r = 0,算法结束;b 即为答案。
2. 互换:置 a←b,b←r,并返回第一步。
写成代码,使用迭代法即可得到:

int gcd(int a, int b)
{
 	return (b==0? a: gcd(b, a%b));
}

得到之后,然后用 c 对得到的最大公约数求余(%),判断余数是否为零。但是,我提交之后会报错,Runtime Error(FPU),经过查错,知道问题出在 除数为零

辗转相除法,一旦有输入其中一个或者两个数为零,不会报错而是会得到结果最大公约数为0. 这种情形需要单独讨论。

求余操作%,允许被除数或者除数为负数,即3%-3=0,同时-3%3=0,-3%3=0;或者被除数是零,即0%3=0. 但是决不允许除数为零,所以需要单独判断。

但是,如果有三个输入呢?即 ax+by+cz = d 是否能找到整数值的 x,y,z 解的问题。求三个数的最大公约数怎么求呢?可以参考:http://zhidao.baidu.com/question/94653009.html,先求出两个数的最大公约数m,再将m同第三个数求最大公约数。同理,四个、五个数的公约数也能求得。


你可能感兴趣的:(c,最大公约数,辗转相除,woj)