By 鲍建敏
最近在pongo.cn上看到了这道题,题目如下:
有两个容器,容积分别为A升和B升,有无限多的水,现在需要C升水。 我们还有一个足够大的水缸,足够容纳C升水。起初它是空的,我们只能往水缸里倒入水,而不能倒出。 可以进行的操作是: 把一个容器灌满; 把一个容器清空(容器里剩余的水全部倒掉,或者倒入水缸); 用一个容器的水倒入另外一个容器,直到倒出水的容器空或者倒入水的容器满。 问是否能够通过有限次操作,使得水缸最后恰好有C升水。 输入:三个整数A, B, C,其中 0 < A , B, C <= 1000000000 输出:0或1,表示能否达到要求。 函数头部: c语言:1表示可以,0表示不可以 int can(int a,int b,int c); c++语言: true表示可以,false表示不可以 bool can(int a,int b,int c); java语言:true表示可以,false表示不可以 public class Main { public static boolean can(int a,int b,int c); }
我的思路:
1. 初想
觉得这个题目很简单啊,就是将较大的容器装满水向较小的容器里面倒,然后能够产生另外一个可以作为基数升的容器,所以就写代码以一个较小的容器容量和差容量为基数的累积问题,直接用了for循环的方法。提交代码发现是错的
2. 再想
既然较大容器的可以装满水向较小容器里面倒那么较小容器肯定也能装满水向较大的容器里面倒,这又会产生很多基数,比如是2升的和5升的,2升装满了向5升容器中倒,第三次,等5升满了,产生了一个1升的基数。这样的话,所有整数升的容器都能装满了。这让我联想到一般情况,如果是两个不同升的容器,它们会产生什么样的基数。这让我想到了最大公约数(通过实例也给了我这样的想法)。其实两个容器能够产生的最小基数便是这个最大公约数,而且这个最大公约数也是他们差的最大公约数。同时也是它们 |A*a - B*b| 的最大公约数,我没证明过。只是我臆测,有机会可以证明一下。所以所有的问题就归结为求 a 和 b 的最大公约数的问题了,然后比较c 是否能整除这个最大公约数了。
3. 代码
代码我是用java实现的,写的时间不长,多指教。
import java.io.*; import java.math.BigInteger; import java.util.*; public class test { public static boolean can(int a, int b, int c) { int d = 0; int a1 = a; int b1 = b; if (a1 < b1) { while ((d = a1 % b1) != 0) { d = a1 % b1; a1 = b1; b1 = d; } d = b1; } else { while ((d = b1 % a1) != 0) { d = b1 % a1; b1 = a1; a1 = d; } d = a1; } if ((c % d) == 0) { return true; } return false; } public static void main(String args[]) { boolean result = false; int a = 1234567; int b = 7654321; int c = 9999999; result = can(a, b, c); System.out.println(result); }
}