题目
恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,
使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
乱说几句
题目并不是特别特别难,但是这道题目的思想十分的好,在很多其它的题目中也有体现这个思想。
题解
假如我们现在当前这个序列中,交换两个相邻的大臣(假设他们是i和i+1大臣),很容易想到交换他们两个是不会影响其他大臣的奖赏的,(首先,交换这两个大臣,与前i-1个是毫无干系的,齐次,交换之后,乘积没有变,自然后面的大臣的奖赏都没有变,变的只是i和i+1大臣),我们假设第i个大臣的左手和右手分别为a,b,i+1大臣的左右手分别为c,d,记前i-1位大臣的左手的乘积为s,没有交换这两个大臣时这两个大臣的奖赏的最大值为N,以及交换这两个大臣时这两个大臣的奖赏的最大值为M。假设
a×b≤c×d
那么
N=
max{s÷b,s×a÷d}
M=
max{s÷d,s×c÷b}
因为
a×b≤c×d
所以
s×a÷d≤s×c÷b
又因为
s÷d≤s×a÷d
所以
s÷d≤s×a÷d≤s×c÷b
所以M=
s×c÷b
显然
s÷b≤s×c÷b
,又由上面的结论得出
s×a÷d≤s×c÷b
,
综上
N≤M
,也就是说i大臣要排在j大臣前面的条件为(设i大臣的左右手分别为a[i],b[i])
a[i]×b[i]≤a[j]×b[j]
,最后因为数据太大,套上高精度。
给出大佬的代码参考。(题解版)
var s,ans,d:array[0..1100] of longint;
a,b,c:array[0..1100] of longint;
n:longint;
procedure init;
var i,k:longint;
begin
readln(n);
for i:=0 to n do begin
readln(a[i],b[i]);
c[i]:=a[i]*b[i];
end;
while a[0]<>0 do begin
inc(s[0]);
s[s[0]]:=a[0] mod 10000;
a[0]:=a[0] div 10000;
end;
end;
procedure qsort(x,y:longint);
var i,j,mid,mi,t:longint;
begin
i:=x;
j:=y;
mid:=c[(x+y) shr 1];
mi:=a[(x+y) shr 1];
while i<j do begin
while (c[i]<mid)or(c[i]=mid)and(a[i]<mi) do inc(i);
while (c[j]>mid)or(c[j]=mid)and(a[j]>mi) do dec(j);
if i<=j then begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
t:=b[i];
b[i]:=b[j];
b[j]:=t;
t:=c[i];
c[i]:=c[j];
c[j]:=t;
inc(i);
dec(j);
end;
end;
if i<y then qsort(i,y);
if j>x then qsort(x,j);
end;
procedure times(t:longint);
var i,g:longint;
begin
g:=0;
for i:=1 to s[0] do begin
s[i]:=s[i]*t+g;
g:=s[i] div 10000;
s[i]:=s[i] mod 10000;
end;
s[s[0]+1]:=g;
while s[s[0]+1]>0 do begin
inc(s[0]);
s[s[0]]:=s[s[0]-1] div 10000+s[s[0]];
s[s[0]-1]:=s[s[0]-1] mod 10000;
end;
end;
procedure divide(t:longint);
var g,i:longint;
p:boolean;
begin
g:=0;
for i:=s[0] downto 1 do begin
d[i]:=(s[i]+g*10000) div t;
g:=(s[i]+g*10000) mod t;
end;
p:=false;
for i:=s[0] downto 1 do
if d[i]<>0 then begin
p:=true;
break;
end;
if p then d[0]:=i;
p:=false;
if d[0]>ans[0] then p:=true else
if d[0]<ans[0] then p:=false else begin
for i:=ans[0] downto 1 do begin
if d[i]>ans[i] then begin
p:=true;
break;
end;
end;
end;
if p then ans:=d;
end;
procedure main;
var i,ll:longint;
begin
qsort(1,n);
for i:=1 to n do begin
divide(b[i]);
times(a[i]);
end;
end;
procedure print;
var i,j:longint;
sa:string;
begin
write(ans[ans[0]]);
for i:=ans[0]-1 downto 1 do begin
str(ans[i],sa);
for j:=1 to 4-length(sa) do write(0);
write(ans[i]);
end;
end;
begin
init;
main;
print;
end.
const
maxn=1000+5;
maxv=1000000+5;
var
a,b,c:array[-1..maxn] of longint;
num:array[0..maxv] of longint;
i,n,len:longint;
procedure swap(var a,b:longint);
var
t:longint;
begin
t:=a;
a:=b;
b:=t;
end;
procedure qsort(x,y:longint);
var
i,j,mid:longint;
begin
i:=x;
j:=y;
mid:=c[(i+j)>>1];
repeat
while c[i]<mid do inc(i);
while c[j]>mid do dec(j);
if i<=j then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
swap(c[i],c[j]);
inc(i);
dec(j);
end;
until i>j;
if i<y then qsort(i,y);
if x<j then qsort(x,j);
end;
procedure cheng(x:longint);
var
i:longint;
begin
for i:=1 to len do
num[i]:=num[i]*a[x];
for i:=1 to len do
begin
num[i+1]:=num[i+1]+num[i] div 10;
num[i]:=num[i] mod 10;
end;
inc(len);
while num[len]>9 do
begin
num[len+1]:=num[len+1]+num[len] div 10;
num[len]:=num[len] mod 10;
inc(len);
end;
if num[len]=0 then
dec(len);
end;
procedure chu;
var
i:longint;
begin
for i:=len downto 1 do
begin
num[i-1]:=num[i-1]+(num[i] mod b[n])*10;
num[i]:=num[i] div b[n];
end;
while num[len]=0 do dec(len);
if len=0 then
write('1');
end;
begin
{assign(input,'jzoj3100.in');
reset(input);
assign(output,'jzoj3100.out');
rewrite(output);}
readln(n);
readln(a[0],b[0]);
for i:=1 to n do
begin
readln(a[i],b[i]);
c[i]:=a[i]*b[i];
end;
qsort(1,n);
len:=1;
num[1]:=a[0];
for i:=1 to n-1 do
cheng(i);
chu;
for i:=len downto 1 do
write(num[i]);
{close(input);
close(output);}
end.
目前oj最强版
const mo=10000000000;
var n,i,p,k,max:longint;
ans:array[0..400] of int64;
begin
readln(n);
ans[0]:=1;
readln(ans[1]);
for i:=1 to n do
begin
readln(p,k);
if p*k>max then max:=p*k;
ans[1]:=ans[1]*p;
k:=0;
while (ans[k+1]>0) or (k<ans[0]) do
begin
inc(k);
ans[k+1]:=ans[k+1]*p+ans[k] div mo;
ans[k]:=ans[k] mod mo;
end;
ans[0]:=k;
end;
for i:=ans[0] downto 2 do
begin
ans[i-1]:=ans[i-1]+ans[i] mod max*mo;
ans[i]:=ans[i] div max;
end;
ans[1]:=ans[1] div max;
while (ans[ans[0]]=0) and (ans[0]>1) do dec(ans[0]);
if (ans[0]=1) and (ans[1]=0) then ans[1]:=1;
write(ans[ans[0]]);
for i:=ans[0]-1 downto 1 do
begin
ans[0]:=mo;
while ans[0]>10 do
begin
ans[0]:=ans[0] div 10;
if ans[i]<ans[0] then write(0);
end;
write(ans[i]);
end;
end.
the end
thank you!