NOIP2012 國王遊戲 題解

2021-07-04 12:53:59 字數 3208 閱讀 1436

恰逢h國國慶,國王邀請n位大臣來玩乙個有獎遊戲。首先,他讓每個大臣在左、右手上面分別寫下乙個整數,國王自己也在左、右手上各寫乙個整數。然後,讓這n位大臣排成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每位大臣獲得的金幣數分別是:排在該大臣前面的所有人的左手上的數的乘積除以他自己右手上的數,然後向下取整得到的結果。 

國王不希望某乙個大臣獲得特別多的獎賞,所以他想請你幫他重新安排一下隊伍的順序,使得獲得獎賞最多的大臣,所獲獎賞盡可能的少。注意,國王的位置始終在隊伍的最前面。

第一行包含乙個整數n,表示大臣的人數。 

第二行包含兩個整數a和b,之間用乙個空格隔開,分別表示國王左手和右手上的整數。接下來n行,每行包含兩個整數a和b,之間用乙個空格隔開,分別表示每個大臣左手和右手上的整數。

輸出只有一行,包含乙個整數,表示重新排列後的隊伍中獲獎賞最多的大臣所獲得的金幣數。

3 

1 1

2 3

7 4

4 6

2

每個測試點1s

對於20%的資料,有1≤ n≤ 10,0 < a、b < 8; 

對於40%的資料,有1≤ n≤20,0 < a、b < 8; 

對於60%的資料,有1≤ n≤100; 

對於60%的資料,保證答案不超過10^9; 

對於100%的資料,有1 ≤ n ≤1,000,0 < a、b < 10000。

貪心證明

假設相鄰的兩個人左右手分別是(a, b), (a, b)。設a * b <= a * b,i之前所有人的左手乘積為s。

則,ans1 = max

若交換則,ans2 = max

因為,a * b <= a * b

所以,s * a / b <= s * a / b

又因為,s / b <= s * a / b

所以,ans2 = s * a / b

ans1 = max

所以,ans1 <= ans2

證畢首先我們分析一下如果i

和j兩個相鄰那麼i排在

j前面的必要條件是

total *a[i] /

b[j]  <  total * a[j] /b[i]

也就是說

a[i]*b[i]

而本題中,n《

1000,a

,b《10000  1000

個10000

乘起來。。。。

所以要用高精度,而高精度是以字元讀入,那前面的排序要用一遍,麻煩。。。

所以本段程式有了改進:平時的精度陣列只存乙個一位數,這段程式存了每個大臣的數,每一次乘完都更新一遍,這樣以後就可以讀入時就處理好先後順序,程式還很短。

【程式】

var i,n,l:longint;  //l表示高精度中字串的長度

a,b,c:array[0..100001] of longint; //a表示乘積,b表示左手,c表示右手

g:array[0..1000000] of longint;

procedure gj1;   //高精乘

varj:longint;

begin

forj:=1 to l do g[j]:=g[j]*b[i];  //每乙個都乘

forj:=1 to l do

begin

g[j+1]:=g[j+1]+g[j] div 10;  //進製

g[j]:=g[j] mod 10;  //進製後處理

end;

inc(l); //長度加一

while g[l]>9 do  

begin

g[l+1]:=g[l+1]+g[l] div 10;  //單個位上》9 進製

g[l]:=g[l] mod 10;  //進製後處理

inc(l);  //長度加一

end;

ifg[l]=0 then dec(l);  //陣列末位(數的首位)為0,出陣列

end;

procedure gj2;   //除法

var j:longint;

begin

forj:=l downto 1 do

begin

g[j-1]:=g[j-1]+(g[j] mod c[n])*10; //將前一位mod 第n位大臣右手給下一位(對於數來說)

g[j]:=g[j] div c[n];   //處理這一位

end;

while g[l]=0 do dec(l);   //處理首位

ifl=0 then writeln('1');  //防止減完

end;

procedure qsort(l,r:longint); //快排

vari,j,x,y:longint;

begin

i:=l;

j:=r;

x:=a[(l+r) div 2];

repeat

while a[i]

while x

if i<=j then

begin

y:=a[i]; a[i]:=a[j]; a[j]:=y;

y:=b[i]; b[i]:=b[j]; b[j]:=y;   //每個人對應的三個陣列都要跟著換

y:=c[i]; c[i]:=c[j]; c[j]:=y;

inc(i); dec(j);

end;

until (i>j);

iflifi

end;

begin

readln(n);

readln(b[0],c[0]);  //讀入國王,國王不參與排序,所以『0』

fori:=1 to n do    //讀入大臣,並計算左手*右手

begin

read(b[i],c[i]);

a[i]:=b[i]*c[i];

end;

qsort(1,n); //排序,原理見題解

l:=1;

g[1]:=b[0];  //從國王左手開始乘,賦初值

fori:=1 to n-1 do gj1;      gj2;     //最後乙個得到的最多,所以由n-1個左手乘積/第n個右手乘積

fori:=l downto 1 do write(g[i]);  //倒序輸出

writeln;

end.

noip2012國王遊戲

game.cpp c pas 問題描述 恰逢 h 國國慶,國王邀請 n 位大臣來玩乙個有獎遊戲。首先,他讓每個大臣在左 右 手上面分別寫下乙個整數,國王自己也在左 右手上各寫乙個整數。然後,讓這 n位大臣排 成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每 位大臣獲得...

NOIP2012 國王遊戲

題解 一開始看著題覺得是二分答案 最大值的最小值 後來發現不滿足單調性 再後來發現可以用貪心做 只需把大臣按照左手 右手公升序排序即可 證明 很顯然前面的大臣位置隨便調換對後面的大臣並沒有影響 那麼假設現在已經排了i 1個大臣,p a 1 a 2 a 3 a i 1 第i個大臣的錢w i p b i...

NOIP2012國王遊戲

用貪心可以解決。將所有人按左右手的乘積排序,這樣一定可以保證結果最優。現給出證明 首先,任意相鄰兩人的順序對於排在他們前面和後面的人沒有影響。顯然 兩人左右手上的數字分別為l 1 r 1 l 2 r 2 令l 1 r 1 若1在2前面,那麼兩人分得的金幣分別為sum r 1 sum l 1 r 2 ...