【NOIP2012DAY1】国王游戏

题目

恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这n位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。 国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,
使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

乱说几句

题目并不是特别特别难,但是这道题目的思想十分的好,在很多其它的题目中也有体现这个思想。

题解

假如我们现在当前这个序列中,交换两个相邻的大臣(假设他们是i和i+1大臣),很容易想到交换他们两个是不会影响其他大臣的奖赏的,(首先,交换这两个大臣,与前i-1个是毫无干系的,齐次,交换之后,乘积没有变,自然后面的大臣的奖赏都没有变,变的只是i和i+1大臣),我们假设第i个大臣的左手和右手分别为a,b,i+1大臣的左右手分别为c,d,记前i-1位大臣的左手的乘积为s,没有交换这两个大臣时这两个大臣的奖赏的最大值为N,以及交换这两个大臣时这两个大臣的奖赏的最大值为M。假设 a×bc×d 那么
N= max{s÷b,s×a÷d}
M= max{s÷d,s×c÷b}
因为 a×bc×d
所以 s×a÷ds×c÷b
又因为 s÷ds×a÷d
所以 s÷ds×a÷ds×c÷b
所以M= s×c÷b
显然 s÷bs×c÷b ,又由上面的结论得出
s×a÷ds×c÷b
综上 NM ,也就是说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!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值