题解 P1080 【国王游戏】

hicc0305

2018-07-05 14:56:39

Solution

这道题首先想到需要排序,可是按什么顺序排呢? 这就需要推导了 对于任意一个人i和j,假设i在j前面,i之前所有人的乘积为k1,i~j之间(不包括i,j)的乘积为k2 则此时两人的最大值为max(k1/bi,k1·ai·k2/bj) 如果交换两人的最大值为max(k2/bj,k1·aj·k2/bi) 显然k1·ai·k2/bj>k2/bj,k1·aj·k2/bi>k1/bi 所以如果k1·aj·k2/bi<k1·ai·k2/bj即aj·bj<ai·bi,交换后的最大值就比交换前的最大值小,就需要交换。按照这个比较法sort一下就可以了 剩下的就是枚举1~n,每一个都算一遍取最大。(注意要用高精,打的有点乱。。) ```cpp #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n; int ans[100000],la=0,res[100000]; struct peo { int a,b; }p[1100]; bool cmp(peo x,peo y) { return (x.a*x.b)<(y.a*y.b);//按照 两个值的乘积进行排序 } int m[100000],l=1; void mutiply(int x)//高精乘法 { int add=0; for(int i=1;i<=l+10;i++) { int tmp=m[i]*x+add; m[i]=tmp%10; add=tmp/10; } l+=10; while(m[l]==0) l--; } void get(int x) { memset(res,0,sizeof(res)); int tmp,l1=0; for(int i=l;i>=1;i--) { tmp=tmp*10+m[i],l1++; if(tmp<x) continue; res[l1]=tmp/x; tmp%=x; }//高精除法,注意我存的时候正过来存的,所以还要倒过来一下 for(int i=1;i<=(l1+1)/2;i++) swap(res[i],res[l1-i+1]); while(res[l1]==0 && l1>1) l1--; //比较大小 if(l1>la) { la=l1; for(int i=la;i>=1;i--) ans[i]=res[i]; } else if(l1==la) { int f=0; for(int i=la;i>=1;i--) { if(ans[i]<res[i]) { f=1; break; } if(ans[i]>res[i]) break; } if(f) { for(int i=la;i>=1;i--) ans[i]=res[i]; } } } int main() { scanf("%d",&n); for(int i=0;i<=n;i++) scanf("%d%d",&p[i].a,&p[i].b); sort(p+1,p+n+1,cmp); m[1]=1; for(int i=1;i<=n;i++) { mutiply(p[i-1].a); get(p[i].b); } if(ans[la]==0) la--; for(int i=la;i>=1;i--) printf("%d",ans[i]); return 0; } ```