uva 571 Jugs
数论题
题意:
有无限的水供应,另外有AB两个杯子,他们有容量,分别为ca和cb,满足0<ca<=cb,并且ca和cb互质
一开始两个杯子都没有水。一种操作是,你能往一个杯子加水,但必须把这个杯子加满,一种操作是倒水,但一定要把水倒空,一种操作是把一个杯子的水倒给另一个杯子,但要求是至少使一个杯子为空或者另一个杯子。现在给你一个数字n,n<=cb,现在的任务是使B杯的水量为n,至于A杯的水量是多少都行,问你要怎么做。
这题对于一个case其实有多种答案,不过题目对于输出并没有要求并没有需要优化,任意一组可行解即可
这题一开始没有头绪,从推理的角度来看这题,但是一直找不到出路。题目归类在数学类,条件中ca与cb互质,这个东西肯定有用,但是想不出来。后来看了一下题解,明白了,所以自己写一下证明
先来看一个特列: 由于 0<ca<=cb , N<=cb 且题目保证一定有解,所以当ca=cb时,不难推理出必然有N=ca=cb,这样的话,只要一步操作就是往B中加满水。
当 ca<cb , N=cb, 同样是一步操作往B中加满水。 所以特殊情况就是N=cb,直接往B中加水
下面讨论的是N<cb
1.来看一个式子 x*A , B , 其中x的范围是[1,B-1],x*A无法被B整除,(因为A与B互质,A不能整除B(没有任何除了1以外的公因子),x也不可能整除B,因而x*A不可能整除B)
2.那么x*A mod B=r ,且r!=0;下面证明一个最重要的结论,当 x1!=x2是,r1!=r2
反证法:假设:x1!=x2,r1=r2
我们先约定x1>x2,r1=r2=r
x1*A = m1*B+r;
x2*A = m2*B+r;
上面两式相减 (x1-x2)*A=(m1-m2)*B ------> (x1-x2)*A/B=m1-m2
换句话说,(x1-x2)*A能被B整除,而1<=x1-x2<=B-1,这与第1条结论是矛盾的
所以假设不成立,当x1!=x2时,r1!=r2
3.基于1和2,可以得到最后的结论 x*A , x范围[1,B-1] , 而x不同时,r也不同,可知知道,当x从1到B-1枚举,r的取值也将在[1,B-1],只是顺序不一定
换句话说,x枚举完,就能得到所有可能的r值,而N<cb,一定会得到一个N的值
4.最后就是代码实现,只要理清一下逻辑关系即可
#include <cstdio> #include <cstring> int ca,cb,n,a,b; int main() { while(scanf("%d%d%d",&ca,&cb,&n)!=EOF) { if(cb==n) { printf("fill B\n"); printf("success\n"); continue; } a=b=0; while(b!=n) { if(a==0) //A瓶为空,加满 { printf("fill A\n"); a=ca; } if(b<cb) //b瓶没没有满 { printf("pour A B\n"); if(b+ca>cb) //B先满,A不为空 { a=ca-(cb-b); b=cb; } else //A为空,B未满或者满都有可能 { b=b+a; a=0; } } if(b==cb) { printf("empty B\n"); b=0; printf("pour A B\n"); b=a; a=0; } } printf("success\n"); } return 0; }