1. 程式人生 > >【NOIP2012提高組】國王遊戲

【NOIP2012提高組】國王遊戲

Description

恰逢H國國慶,國王邀請n位大臣來玩一個有獎遊戲。首先,他讓每個大臣在左、右

手上面分別寫下一個整數,國王自己也在左、右手上各寫一個整數。然後,讓這n位大臣排

成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每

位大臣獲得的金幣數分別是:排在該大臣前面的所有人的左手上的數的乘積除以他自己右

手上的數,然後向下取整得到的結果。

國王不希望某一個大臣獲得特別多的獎賞,所以他想請你幫他重新安排一下隊伍的順序,

使得獲得獎賞最多的大臣,所獲獎賞儘可能的少。注意,國王的位置始終在隊伍的最前面。

Solution

用什麼演算法

首先看到最大最小的,想到了二分。推著推著推不出來,╮(╯▽╰)╭,二分


不過仔細想了一想,要求一個序列,並且改一下位置答案可能就不同,那麼就是有優先順序……貪心!!!排序!!!

演算法如何解題

看到第一個肯定不變,那麼還與什麼可以確定。我們發現最後一個人的答案,是這個人在所有順序中的值最大的情況。有意思。進一步思考,所有人左手的乘積為Z,當他最後時,答案是Zl[i]r[i],好像l[i]r[i]越大,那麼這個人的貢獻就越小,而且在其他排序下不會有其他位置的貢獻總貢獻比當前更小的了。因為如果選的是其他人在最後一位,那麼假設就交換一下位置,那麼兩個位置的答案總和更大。
證明:設l1,r1與l2,r2交換位置,l1之前的l乘積為Z1,l1之後的乘積為Z2
沒換之前的答案:Z

1l1r1+Z1Z2l2r2
換了之後的答案:Z1l2r2+Z1Z2l1r1
把兩個式子移項之後就是
Z1(Z21)l2r2?Z1(Z21)l1r1
Z1(Z21)l1r1Z1(Z21)l2r2
因為l1r1< l2r2,所以前項<後項
為什麼考慮二元組的和呢?因為交換位置之後一個變大,一個變小,那麼比較一下和再很據l1r1< l2r2之類的就可以分別出這樣更優了。
根據上面的證明,按照l*r從小到大排一次續然後依次模擬就可以了。

記得要打高進度

可惜,考場沒打高進度

Code

#include<iostream> 
#include<cstdio>
#include<algorithm> #include<cstring> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) #define fod(i,a,b) for(i=a;i>=b;i--) #define ll long long const int maxn=5007; using namespace std; ll i,j,k,n,m,yi,er,r,mid,l,t; int ans[maxn],ans1[maxn],b[maxn]; char s[maxn],st[maxn]; struct node{ ll a,b,c; }a[maxn]; bool cmp(node x,node y){ return x.c<y.c; } void cheng(ll x){ memset(b,0,sizeof(b)); ll i,j,k,l,o=0; fo(i,1,ans1[0]){ b[i]=b[i]+ans1[i]*x+o; b[i+1]+=b[i]/10; b[i]=b[i]%10; } for(b[0]=ans1[0];b[b[0]+1];){ b[++b[0]+1]+=b[b[0]]/10; b[b[0]]=b[b[0]]%10; } fo(i,0,maxn) ans1[i]=b[i]; } void chu(ll x){ ll i,j,k,o=0; fod(i,1,b[0])b[i]=0; b[0]=0; memset(b,0,sizeof(b)); fod(i,ans1[0],1){ o=o*10+ans1[i]; if(o>=x){ if(b[0]==0) b[0]=i; b[i]=o/x; o=o%x; } } } void bijiao(){ ll i,j,k,l; if(b[0]>ans[0]){ fo(i,0,maxn) ans[i]=b[i]; } else if(b[0]==ans[0]){ fod(i,ans[0],1){ if(b[i]>ans[i]){ fo(j,0,maxn) ans[j]=b[j]; return; } } } } int main(){ scanf("%d",&n); scanf("%s",s+1); fod(i,strlen(s+1),1)ans1[++ans1[0]]=s[i]-'0'; scanf("%d",&er); t=yi; fo(i,1,n){ scanf("%lld%lld",&a[i].a,&a[i].b); a[i].c=a[i].a*a[i].b; } sort(a+1,a+n+1,cmp); fo(i,1,n){ chu(a[i].b); bijiao(); cheng(a[i].a); if(i==95){ n=n; } } fod(i,ans[0],1)printf("%d",ans[i]); }