题目链接
https://cn.vjudge.net/problem/UVA-571
分析
刚做了道倒水问题的题想看看能不能水二倍经验,结果发现了这道题
题意翻译:https://www.cnblogs.com/devymex/archive/2010/08/04/1792288.html
设A容量$x$,B容量$y$
我们把将水倒入A视为$+x$,将倒空B视为$-y$,若A满,就倒入B视为$-x$
由于$a,b$是互质的,根据裴蜀定理一定有$x,y$保证有$ax+by=gcd(a,b)=1$,又因为$y>=c>=x>=0$那么也就保证了一定存在非负整数$x$和一个整数$y$使得$ax+by=c$.
于是一开始我的思路是运用扩展$GCD$求出一组解后将$x$转化为一个非负数解.然后按步骤模拟就好了
然而在我写模拟步骤时忽然发现完全不用扩欧啊,我们的模拟过程其实就是:
若A空,则将A倒满
若B满,将B倒空
若A满,将A中水倒入B中
由于题目要求输出一种解就好了于是我们直接模拟就好了,至于为什么会这样,我好像还找不到较为严谨的数学证明
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cctype> #include <vector> #define ll long long #define ri register int using std::min; using std::max; using std::swap; template <class T>inline void read(T &x){ x=0;int ne=0;char c; while(!isdigit(c=getchar()))ne=c=='-'; x=c-48; while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48; x=ne?-x:x;return ; } int ex_gcd(int a,int b,int x,int y){ if(!b){ x=1,y=0; return a; } int d=ex_gcd(b,a%b,x,y); int z=x;x=y,y=z-(a/b)*y; return d; } int a,b,c; int main(){ int x,y,lef; int bot[3]; while(scanf("%d %d %d",&a,&b,&c)!=EOF){ bool flag=1; if(b==c){ puts("fill B"); puts("success"); flag=0; } bot[1]=bot[2]=0; while(1&&flag){ if(bot[2]==c){ puts("success"); break; } if(!bot[1]){ bot[1]=a; puts("fill A"); } else if(bot[2]==b){ puts("empty B"); bot[2]=0; } else if(bot[1]){ lef=b-bot[2]; if(lef<bot[1]){ bot[1]-=lef; bot[2]+=lef; } else { bot[2]+=bot[1]; bot[1]=0; } puts("pour A B"); } } } return 0; }
|