luogu P1080 國王遊戲
題目描述
恰逢 H 國國慶,國王邀請 n 位大臣來玩一個有獎遊戲。首先,他讓每個大臣在左、右手上面分別寫下一個整數,國王自己也在左、右手上各寫一個整數。然後,讓這 n 位大臣排成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若幹金幣,每位大臣獲得的金幣數分別是:排在該大臣前面的所有人的左手上的數的乘積除以他自己右手上的數,然後向下取整得到的結果。
國王不希望某一個大臣獲得特別多的獎賞,所以他想請你幫他重新安排一下隊伍的順序,使得獲得獎賞最多的大臣,所獲獎賞盡可能的少。註意,國王的位置始終在隊伍的最前面。
輸入輸出格式
輸入格式:
第一行包含一個整數 n,表示大臣的人數。
第二行包含兩個整數 a和 b,之間用一個空格隔開,分別表示國王左手和右手上的整數。
接下來 n 行,每行包含兩個整數 a 和 b,之間用一個空格隔開,分別表示每個大臣左手和右手上的整數。
輸出格式:
輸出只有一行,包含一個整數,表示重新排列後的隊伍中獲獎賞最多的大臣所獲得的金幣數。
輸入輸出樣例
輸入樣例#1:3 1 1 2 3 7 4 4 6輸出樣例#1:
2
說明
【輸入輸出樣例說明】
按 1、2、3 號大臣這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 2;
按 1、3、2 這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 2;
按 2、1、3 這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 2;
按 2、3、1 這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 9;
按 3、1、2 這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 2;
按 3、2、1 這樣排列隊伍,獲得獎賞最多的大臣所獲得金幣數為 9。
因此,獎賞最多的大臣最少獲得 2 個金幣,答案輸出 2。
【數據範圍】
對於 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。
NOIP 2012 提高組 第一天 第二題
first 20:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int N=1010; struct node{ int l,r; }dow[N],king; int n; inline int read() { int x=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c=getchar(); while(c>=‘0‘&&c<=‘9‘)x=x*10+c-‘0‘,c=getchar(); return x; } inline bool cmp(node a,node b) { if(a.l==b.l) return a.r>b.r; else return a.l<b.l; } int main() { n=read(); king.l=read(),king.r=read(); for(int i=1;i<=n;i++) dow[i].l=read(),dow[i].r=read(); sort(dow+1,dow+n+1,cmp); ll maxans=0; for(int i=1;i<=n;i++) { ll pre=king.l; for(int j=1;j<i;j++) pre*=dow[j].l; maxans=max(maxans,pre/dow[i].r); } printf("%d",maxans); return 0; } /* 3 1 1 2 3 7 4 4 6 */
#include<cstdio> #include<cstring> using namespace std; int n,ab[1009][3],sum[1009],now[1009],ans[1009],t,kk; void print(int p[])//輸出 { printf("%d",p[p[0]]); for(int i=p[0]-1;i>=1;i--) { printf("%d",p[i]/1000); printf("%d",p[i]/100%10); printf("%d",p[i]/10%10); printf("%d",p[i]%10); } return; } int bj(int a[],int b[])//比較兩個大數大小 { if(a[0]<b[0]){return 1;} if(a[0]==b[0]) { for(int i=a[0];i>=1;i--) { if(a[i]>b[i]){return 0;} if(a[i]<b[i]){return 1;} } } return 0; } void copy(int a[],int b[])//把b數復制給a數 { a[0]=b[0]; for(int i=1;i<=b[0];i++){a[i]=b[i];} return; } void div(int a[],int b,int c,int d[])//高精除低精 { kk=0;//存余數 for(int i=d[0];i>=1;i--) { kk=kk*10000+d[i], a[i]=kk/b, kk=kk%b;//余數要帶到下一位 } } int main() { freopen("kinggame.in","r",stdin); freopen("kinggame.out","w",stdout); scanf("%d%d%d",&n,&ab[0][1],&ab[0][2]);//輸入 for(int i=1;i<=n;i++){scanf("%d%d",&ab[i][1],&ab[i][2]);} sum[0]=1,sum[1]=1;//初始值 for(int i=1;i<n;i++) { for(int j=i+1;j<=n;j++) { if(ab[i][1]*ab[i][2]>ab[j][1]*ab[j][2])//冒泡 { t=ab[i][1],ab[i][1]=ab[j][1],ab[j][1]=t, t=ab[i][2],ab[i][2]=ab[j][2],ab[j][2]=t; } } } for(int i=1;i<=n;i++) { for(int j=1;j<=sum[0];j++){sum[j]=sum[j]*ab[i-1][1];}//先乘上上一個人左手上的數 for(int j=1;j<=sum[0];j++) { sum[j+1]=sum[j+1]+sum[j]/10000, sum[j]=sum[j]%10000; } while(sum[sum[0]+1]>0){sum[0]++;} div(now,ab[i][2],i,sum);//除法,結果存在now上 now[0]=sum[0];//復制位數 while(now[now[0]]==0){now[0]--;} if(bj(ans,now)){copy(ans,now);}//如果now比ans大,把ans替換成now } print(ans); return 0; }
luogu P1080 國王遊戲