首页 > 代码库 > luogu P1080 国王游戏

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 longusing 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;}/*31 12 37 44 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 国王游戏