今天在庞果网做了一道题,倒水问题,题目如下,有两个容器,容积分别为A升和B升,有无限多的水,现在需要C升水。 我们还有一个足够大的水缸,足够容纳C升水。起初它是空的,我们只能往水缸里倒入水,而不能倒出。 可以进行的操作是: 把一个容器灌满; 把一个容器清空(容器里剩余的水全部倒掉,或者倒入水缸); 用一个容器的水倒入另外一个容器,直到倒出水的容器空或者倒入水的容器满。问是否能够通过有限次操作,使得水缸最后恰好有C升水。
本小菜鸟对算法题根本就没什么研究,好在有万能的百度,简单看了看,说是欧几里得的算法扩展,百度了下欧几里得算法,其实不过就是辗转相除求最大公约数,高中就有学过这个但是,并不知道叫欧几里得算法。
闲话不多说,还是回到题目,已知容积A升和B升,那么我们能倒出的水的量为,A、B、A-B、A+B四种,也就是说只要判断是否存在这样的x1、x2、x3、x4 令
x1*A+x2*B+x3*(A-B)+x4*(A+B)=C
当然我们可以用循环来进行操作,但是这样显然是费力不讨好的,我们把公式整理一下
(x1+x3+x4)*A+(x2-x3+x4)*B=C
现在就变成了
X*A+Y*B=C
根据欧几里得算法的扩展定理
定理
对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整
数对 x,y ,使得 gcd(a,b)=ax+by。
那么只要C是gcd(a,b)的倍数就返回true,反之返回false。
java实现如下
import java.io.*; import java.math.BigInteger; import java.util.*; public class Main { public static boolean can(int a,int b,int c) { int res; res=mod(a,b); if(c%res==0) return true; else return false; } public static void main(String args[]) { System.out.print(can(0,1,1000000000)); } public static int mod(int a,int b){ if(b>=1){ return mod(b, a%b); } else return a; } }