UVA571Jugs題解--簡單數論(其實是瞎搞)
阿新 • • 發佈:2018-08-28
倒水 blog 翻譯 emp += 非負數 algo system line 使得\(ax+by=c\).
題目鏈接
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\)
於是一開始我的思路是運用擴展\(GCD\)求出一組解後將\(x\)轉化為一個非負數解.然後按步驟模擬就好了
然而在我寫模擬步驟時忽然發現完全不用擴歐啊,我們的模擬過程其實就是:
若A空,則將A倒滿
若B滿,將B倒空
若A滿,將A中水倒入B中
由於題目要求輸出一種解就好了於是我們直接模擬就好了,至於為什麽會這樣,我好像還找不到較為嚴謹的數學證明
代碼
#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){ //int d=ex_gcd(a,b,x,y); bool flag=1; if(b==c){ puts("fill B"); puts("success"); flag=0; } bot[1]=bot[2]=0; //if(x>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"); } //printf("%d %d\n",bot[1],bot[2]); //system("PAUSE"); } //} /*else{ int k=(-c*x)/b+1; x=c*x+k*b,y=c*y-k*a; }*/ } return 0; }
UVA571Jugs題解--簡單數論(其實是瞎搞)