NOIP2012d2t2 国王游戏

来源:互联网 发布:比特币是网络传销吗 编辑:程序博客网 时间:2024/05/16 06:16

原题链接:https://vijos.org/p/1779

题目大意:国王和n个大臣站成一列,编号为0,1,2...n(国王在队首)每个人有两个数字(ai,bi),0<=i<=n

问如何排列大臣的序列,使(a0*a1*...*ai-1/bi)(1<=i<=n)中的最大值最小,求这个最小值


首先注意对于100%的数据,有1 ≤ n ≤1,000,0 < a、b < 10000。——高精度,居然要高精度乘单精度,高精度除单精度。。。

这道题可选的排列太多了,应该贪心,ai*bi越大的,越往后放。

说一下怎么想的:考虑i排在j前的必要条件

假设前面都排好了,前面a的乘积为x,讨论i在j前还是j在i前


不难发现,①<=④,③<=②,那么证明i排在j前更优等价于证明②<④

易得到 i1*i2<j1*j2

所以得到必要条件:ai*bi小于aj*bj

唉,像我这数学不好的以后怎么混啊。。。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=1010;int n;struct rec{int a1,a2,a3;}a[N];struct big{int l,num[N];}sum,ans;int cmp(rec a,rec b){return a.a3==b.a3?a.a2<b.a2:a.a3<b.a3;}big bigcmp(big a,big b){if(a.l>b.l) return a;else if(a.l<b.l)return b;for(int i=a.l-1;i>=0;i--)if(a.num[i]>b.num[i])return a;else if(a.num[i]<b.num[i])return b;//判断时比全了return b;}big  multiply(big a,int b){big c;c.l=a.l;int jw=0;for(int i=0;i<c.l;i++){c.num[i]=jw;c.num[i]+=a.num[i]*b;jw=c.num[i]/10000;c.num[i]%=10000;}while(jw)c.num[c.l++]=jw%10000,jw/=10000;return c;}big minus(big a,int b){big c;c.l=a.l;int jw=0;for(int i=c.l-1;i>=0;i--){int k=a.num[i]+jw*10000;c.num[i]=k/b;jw=k%b;}if(!c.num[c.l-1])c.l--;return c;}void bigprint(big a){printf("%d",a.num[a.l-1]);for(int i=a.l-2;i>=0;i--){if(a.num[i]<1000)printf("0");//数好打几个零if(a.num[i]<100)printf("0");if(a.num[i]<10)printf("0");printf("%d",a.num[i]);}}int main(){freopen("game.in","r",stdin);freopen("game.out","w",stdout);scanf("%d",&n);scanf("%d%d",&a[0].a1,&a[0].a2);for(int i=1;i<=n;i++)scanf("%d%d",&a[i].a1,&a[i].a2),a[i].a3=a[i].a1*a[i].a2;sort(a+1,a+n+1,cmp);ans.l=ans.num[0]=0,sum.l=1,sum.num[0]=a[0].a1;for(int i=1;i<=n;i++){ans=bigcmp(ans,minus(sum,a[i].a2));if(i<n)sum=multiply(sum,a[i].a1);}bigprint(ans);return 0;}


0 0