zoukankan      html  css  js  c++  java
  • 【NOIP】提高组2012 国王游戏

    【题意】

    恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右

    手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这n位大臣排

    成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每

    位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右

    手上的数,然后向下取整得到的结果。

    国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,

    使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

    【算法】贪心(排序)+高精度

    【题解】这是少数不用二分解决最大值最小化问题的题。

    我们考虑将所有大臣按某种条件排序,从而满足该顺序最优。

    考虑当前已有排序,其中某两位置是a1,b1和a2,b2,交换两个位置不能使答案最优需要满足的条件。

    显然交换两位置对前后都没有影响,假设Σai=s,所以交换后不能使答案最优须满足:

    $$max(frac{s}{b_1},frac{sa_1}{b_2})<max(frac{s}{b_2},frac{sa_2}{b_1})$$

    将s提出来,

    $$max(frac{1}{b_1},frac{a_1}{b_2})<max(frac{1}{b_2},frac{a_2}{b_1})$$

    由于ai是正整数,故我们已知:

    $$frac{1}{b_1}<frac{a_2}{b_1} , frac{1}{b_2}<frac{a_1}{b_2}$$

    所以条件转化为:

    $$frac{a_1}{b_2}<frac{a_2}{b_1}$$

    即:

    $$a_1b_1<a_2b_2$$

    所以只要按aibi从小到大排序,一定最优。

    为了找到适合排序的关键字,我们考虑某两位的交换会使排序更优的条件即可得知。

    答案最大可以达到10000^1000即10^4000,要用高精度。(这是NOIP最后一次考高精度,以后不可能再考了)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1010,maxlen=5000;
    struct cyc{int a,b,c;}a[maxn];
    int n,lens,x,lmax,lena;
    int sum[maxlen],ans[maxlen],maxs[maxlen];
    bool cmp(cyc a,cyc b)
    {return a.c<b.c;}
    void cheng(int numi)
    {
        int num=a[numi].a;x=0;
        for(int i=1;i<=lens;i++)
         {
             x+=sum[i]*num;
             sum[i]=x%10;
             x/=10;
         }
        while(x>0)sum[++lens]=x%10,x/=10;
    //    printf("1...%d * lens=%d
    ",numi,lens);
    //    for(int i=1;i<=lens;i++)printf("%d",sum[i]);printf("
    ");
    }
    void divs(int numi)
    {
        int num=a[numi].b;x=0;
        for(int i=lens;i>=1;i--)
         {
             x=x*10+sum[i];
             ans[i]=x/num;
             x%=num;
         }
        lena=lens;
        while(ans[lena]==0&&lena>1)lena--;
    //    printf("1...%d-1/%d / lens=%d
    ",numi,numi,lena);
    //    for(int i=1;i<=lena;i++)printf("%d",ans[i]);printf("
    ");
        bool f=1;
        if(lena>lmax)f=0;else if(lena<lmax)f=1;else
         for(int i=lena;i>=1;i--)
          if(ans[i]>maxs[i]){f=0;break;}else if(ans[i]<maxs[i]){f=1;break;}
        if(!f)
         {
             for(int i=1;i<=lena;i++)maxs[i]=ans[i];
             lmax=lena;
         }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n+1;i++)scanf("%d%d",&a[i].a,&a[i].b),a[i].c=a[i].a*a[i].b;
        sort(a+2,a+n+2,cmp);//for(int i=1;i<=n+1;i++)printf("%d %d
    ",a[i].a,a[i].b);
        sum[(lens=1)]=1;cheng(1);maxs[(lmax=1)]=0;
        for(int i=2;i<=n+1;i++)divs(i),cheng(i);
        for(int i=lmax;i>=1;i--)printf("%d",maxs[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    联考20200725 T1 String
    联考20200723 T1 数
    联考20200722 T3 积木
    联考20200722 T2 ACT4!无限回转!
    联考20200722 T1 集合划分
    联考20200721 T2 s2mple
    联考20200721 T1 s1mple
    联考20200719 T2 寻找规律
    联考20200719 T1 合并奶牛
    联考20200718 T2 树论
  • 原文地址:https://www.cnblogs.com/onioncyc/p/5769789.html
Copyright © 2011-2022 走看看