瓶子和燃料(歐幾里得演算法)
瓶子和燃料
jyy就一直想著儘快回地球,可惜他飛船的燃料不夠了。 有一天他又去向火星人要燃料,這次火星人答應了,要jyy用飛船上的瓶子來換。jyy的飛船上共有 N個瓶子(1<=N<=1000) ,經過協商,火星人只要其中的K 個 。 jyy
將 K個瓶子交給火星人之後,火星人用它們裝一些燃料給 jyy。所有的瓶子都沒有刻度,只
在瓶口標註了容量,第i個瓶子的容量為Vi(Vi 為整數,並且滿足1<=Vi<=1000000000 ) 。
火星人比較吝嗇,他們並不會把所有的瓶子都裝滿燃料。他們拿到瓶子後,會跑到燃料
庫裡鼓搗一通,弄出一小點燃料來交差。jyy當然知道他們會來這一手,於是事先了解了火
星人鼓搗的具體內容。火星人在燃料庫裡只會做如下的3種操作:1、將某個瓶子裝滿燃料;
2、將某個瓶子中的燃料全部倒回燃料庫;3、將燃料從瓶子a倒向瓶子b,直到瓶子b滿
或者瓶子a空。燃料傾倒過程中的損耗可以忽略。火星人拿出的燃料,當然是這些操作能
得到的最小正體積。
jyy知道,對於不同的瓶子組合,火星人可能會被迫給出不同體積的燃料。jyy希望找
到最優的瓶子組合,使得火星人給出儘量多的燃料。
輸入格式
第1行:2個整數N,K,
第2..N 行:每行1個整數,第i+1 行的整數為Vi
輸出格式
僅1行,一個整數,表示火星人給出燃料的最大值。
資料範圍和提示
選擇第2 個瓶子和第 個瓶子,火星人被迫會給出4 體積的容量。
樣例輸入
3 2 3 4 4
樣例輸出
4
思路:
裴蜀定理 對任何整數a、b和它們的最大公約 數d,關於未知數x和y的線性不定方程(稱為裴蜀等式):若a,b是整數,且gcd(a,b)=d,
那麼對於任意的整數x,y,ax+by都一定是d的倍數,特別地,一定存在整數x,y,使ax+by=d成立。
它的一個重要推論是:a,b互質的充要條件是存在整數x,y使ax+by=1.
我們來模擬一下火星人倒燃料的過程:
樣例:3 4 4
顯然只有兩種方案:3 4和4 4
3(①) 4(②):把②倒入燃料,然後倒給①,把①倒掉,於是乎,只剩下②的1單位燃料。
4 4:由於火星人會給你燃料,所以無論怎麼倒都會有一個瓶子有4單位燃料。
結論就顯而易見了,其實就是要從n個數找出k個數,使最大公約數最大。
程式碼:
#include<map> #include<cstdio> using namespace std; int a[1010],p[5000010],t,ans;//a體積,f能裝x體積的個數,p燃料 map<int,int>f; int max(int x,int y){ return x>y?x:y; } int read()//快讀根據自己需要酌情新增 { int x=0,y=1;char c=getchar();while(c<'0'||c>'9'){y=-y;c=getchar();} while(c>='0'&&c<='9'){x=x*10+(c-'0');c=getchar();} return x*y; } int main() { int n=read(),k=read(),i,j; for(i=1;i<=n;i++) { a[i]=read(); for(j=1;j*j<=a[i];j++) { if(a[i]%j!=0) continue; if(!f[j]) p[++t]=j;//第一次進入 f[j]++;//能裝的個數++ if(!f[a[i]/j]) p[++t]=a[i]/j;//同 if(j*j!=a[i]) f[a[i]/j]++;//判相等 } } for(i=1;i<=t;i++) { if(f[p[i]]>=k) ans=max(ans,p[i]);//略 } printf("%d",ans); return 0; ;}