国王游戏 2012年NOIP全国联赛提高组(贪心+高精)
P1080 国王游戏
题目描述
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入输出格式
输入格式:
第一行包含一个整数 n,表示大臣的人数。
第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式:
输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
输入输出样例
3 1 1 2 3 7 4 4 6
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 提高组 第一天 第二题
/* 贪心 对于第 i个大臣和第 j 个大臣: 如果第 i 个大臣放第 j 个大臣前面对答案的贡献小些,那么第 ii 个大臣就放第 jj 个大臣前面 所以就是使 a[i].x/a[j].y<a[j].x/a[i].y 所以就是a[i].x*a[i].y<a[j].x*a[j].y 重载运算符高精 */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define N 1007 using namespace std; int L,R,n; struct node{ int l,r; bool operator < (const node &x) const{ return l*r<(x.l*x.r); } }a[N]; class Big{ public: int size,num[N<<4]; Big(){size=0;memset(num,0,sizeof num);} Big(int data){ size=0; while(data!=0) { size++; num[size]=data%10;data/=10; } } inline void init(int data){ size=0; while(data!=0) { size++; num[size]=data%10;data/=10; } } inline void copy(Big A){ int s1=size,s2=A.size; size=s2; for(int i=s2;i>=1;i--) num[i]=A.num[i]; } }; Big ans,ans1,num,big; inline ll read() { ll x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } Big operator + (Big A,Big B) { Big c; int s=max(A.size,B.size); c.size=s; for(int i=1;i<=s;i++) c.num[i]=A.num[i]+B.num[i]; for(int i=1;i<=s;i++) if(c.num[i]>=10) { c.num[i+1]+=c.num[i]/10; c.num[i]%=10; } if(c.num[s+1]!=0) c.size++; return c; } Big operator - (Big A,Big B) { Big c; int s=max(A.size,B.size); c.size=s; for(int i=1;i<=s;i++) c.num[i]=A.num[i]-B.num[i]; for(int i=1;i<=s;i++) if(c.num[i]<0) { c.num[i+1]-=c.num[i]/10; c.num[i]=c.num[i]%10; } if(c.num[s+1]!=0) c.size++; return c; } ostream & operator << (ostream &os,Big A) { int s=A.size; for(int i=s;i>=1;i--) os<<A.num[i]; return os; } Big operator * (Big A,Big B) { Big c; int s1=A.size,s2=B.size; for(int i=1;i<=s1;i++) for(int j=1;j<=s2;j++) { c.num[i+j-1]+=A.num[i]*B.num[j]; c.num[i+j]+=c.num[i+j-1]/10; c.num[i+j-1]%=10; } c.size=A.size+B.size; while(c.num[c.size]==0) c.size--; return c; } Big operator /(Big A,int b) { Big c; int s1=A.size,k;k=s1; for(int i=s1;i>=1;i--) { c.num[i]=A.num[i]/b; if(i!=1) A.num[i-1]+=(A.num[i]%b*10); A.num[i]/=b; } while(k>=1 && c.num[k]==0) k--;c.size=k; return c; } bool operator > (Big A,Big B) { int s1=A.size,s2=B.size; if(s1<s2) return 0; if(s1>s2) return 1; for(int i=s1;i>=1;i--) if(A.num[i]<B.num[i]) return 0; else return 1; return 0; } int main() { big.init(0); n=read();L=read();R=read(); ans.init(L); for(int i=1;i<=n;i++) a[i].l=read(),a[i].r=read(); sort(a+1,a+n+1); for(int i=1;i<=n-1;i++) { ans1=ans/a[i].r; if(ans1>big) big.copy(ans1); ans1.init(a[i].l);ans=ans*ans1; } ans=ans/a[n].r; if(ans>big) big.copy(ans); cout<<big<<endl; return 0; }