noip 2012 国王游戏(贪心+高精)
/* 我是不会说我考试的时候想到了正解却把金币取大看成金币求和的.... 觉得只按左右手乘积排序不太对 有反例 也可能我反例放到这个题里是错的吧 按自己的理解排的序 就是各种讨论... 假设 第i个人是x1 y1 第i+1个人是x2 y2 前面所有的左手乘积为S 我们通过考虑这两个人决定排序的规则 答案就是 min(max(S/y1,S*x1/y2),max(S/y2,S*x2/y1)) 拿掉S并通分就是 min(max(y2,x1y1),max(y1,x2*y2)) 因为每个max里的值不是只来自一个人 所以不能简单地通过某个值或某几个值来排序 那就讨论吧 ^ ^ 接下来就是神奇(恶心)的高精... */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1010 using namespace std; int n,ans[maxn*5],s[maxn][maxn*5],l[maxn]; struct node{int l,r,s;}p[maxn]; int cmp(node const &x,const node &y) { if(y.r>x.s) { if(x.r>y.s)return y.r<x.r; else return y.r<y.s; } else { if(x.r>y.s)return x.s<x.r; else return x.s<y.s; } } void mul(int k,int x) { int a[maxn*5],len=l[k];memset(a,0,sizeof(a)); for(int i=1;i<=len;i++)a[i]=s[k][i]; for(int i=1;i<=len;i++)a[i]*=x; for(int i=1;i<=len;i++) if(a[i]>9) { a[i+1]+=a[i]/10; a[i]%=10; } while(a[len+1]) { len++; a[len+1]+=a[len]/10; a[len]%=10; } for(int i=1;i<=len;i++)s[k+1][i]=a[i]; l[k+1]=len; } void del(int k,int x) { int a[maxn*5],len=l[k],b[maxn*5],r=0,t=0; memset(a,0,sizeof(a));memset(b,0,sizeof(b)); for(int i=1;i<=len;i++)a[i]=s[k][i]; for(int i=len;i>=1;i--) { r=r*10+a[i];b[i]=r/x;r%=x; } for(int i=len;i;i--) if(b[i]!=0) { t=i;break; } l[k]=t; for(int i=1;i<=len;i++)s[k][i]=b[i]; } void big(int k) { int c[maxn*5];memset(c,0,sizeof(c)); for(int i=1;i<=l[k];i++)c[i]=s[k][i]; if(l[k]>ans[0]) { for(int i=1;i<=l[k];i++) ans[i]=c[i]; ans[0]=l[k]; } else if(l[k]<ans[0])return; else { int falg=0; for(int i=l[k];i>=1;i--) if(c[i]>ans[i]) { falg=1;break; } if(falg==0)return; for(int i=1;i<=l[k];i++) ans[i]=c[i]; ans[0]=l[k]; } } int main() { scanf("%d%d%d",&n,&p[0].l,&p[0].r); for(int i=1;i<=n;i++) scanf("%d%d",&p[i].l,&p[i].r),p[i].s=p[i].l*p[i].r; sort(p+1,p+1+n,cmp); while(p[0].l) { s[0][++l[0]]=p[0].l%10; p[0].l/=10; } for(int i=1;i<=n;i++) mul(i-1,p[i].l); for(int i=1;i<=n;i++) { del(i-1,p[i].r); big(i-1); } for(int i=ans[0];i>=1;i--) printf("%d",ans[i]); return 0; }