zoukankan      html  css  js  c++  java
  • 【noip2012】国王游戏

    题意:

    有n个大臣和一个国王左右手都写了数字 让大臣们站在国王的后面 每个大臣能获得前面所有人左手上数字乘积除以该大臣右手上的数字的金钱 问如何安排大臣顺序 使得获得金钱最多的大臣获得的金钱最少

    题解:

    看到最大值的最小值 最先想到的肯定是二分答案判断答案是否可行

    我有一个思路(未能验证正确性) 从后往前确定某个位置上要放哪个大臣

    求出所有大臣左手乘积*国王左手上的数 再将大臣按左手从大到小排序 找到第一个能放在该位置的大臣(获得金钱<=二分出的mid) 放下去再求下一个大臣

    如果每个大臣都不能放 返回false 否则true

    但是这个方法有个问题 因为它的答案可能达到10^4000 所以二分的复杂度约为O(log(10^4000)) 再乘以检查的O(n^2)

    复杂度达到越O(10^10) 再加上不懂证明检查的正确性 故放弃之= =

    下面来讲下正解

    其实做起来特别简单 重在证明- - 表示半小时拍完1A

    只要将每个大臣按左手值*右手值从小到大排序 一个个放下去 求答案就行了 注意数据很大要打高精

    证明:

    orz神ak的证明方法

    用x[i]、y[i]表示左、右手上的数

    我们证明相邻两人i、i+1 如果x[i]*y[i]>x[i+1]*y[i+1] 那么将他们交换答案不会更差

    设i前所有人左手乘积为a 则交换前两大臣获得的钱分别为a/y[i]、a*x[i]/y[i+1]

    而交换后钱分别为a/y[i+1]、a*x[i+1]/y[i]

    显然 a/y[i+1]<=a*x[i]/y[i+1]

    又因为x[i]*y[i]>x[i+1]*y[i+1]

    所以a*x[i+1]/y[i]<a*x[i]/y[i+1]

    固交换后两大臣的钱都不比交换前第一个大臣的多

    代码:

     1 #include <cstdio>
     2 #include <algorithm>
     3 using std::sort;
     4 const int N=1001;
     5 struct info{
     6     int a[5000];
     7     void print(){
     8         if (!a[0]) puts("0");
     9         else for (int i=a[0];i;i--) printf("%d",a[i]);
    10     }
    11 }ans,sum,one,zero,save;
    12 struct inim{
    13     int x,y;
    14     inim(const int a=0,const int b=0):
    15         x(a),y(b){}
    16 }im[N];
    17 inline bool cmp(inim x,inim y){ return x.x*x.y<y.x*y.y; }
    18 inline info operator *(info a,int b){
    19     info res;
    20     int x=0,l=a.a[0];
    21     for (int i=1;i<=l;i++){
    22         x+=a.a[i]*b;
    23         res.a[i]=x%10;
    24         x/=10;
    25     }
    26     while (x) res.a[++l]=x%10,x/=10;
    27     res.a[0]=l;
    28     return res;
    29 }
    30 inline info operator /(info a,int b){
    31     info res;
    32     int x=0,l=a.a[0];
    33     for (int i=l;i;i--){
    34         x=x*10+a.a[i];
    35         res.a[i]=x/b;
    36         x%=b;
    37     }
    38     while (!res.a[l] && l) --l;
    39     res.a[0]=l;
    40     return res;
    41 }
    42 inline bool operator >(info a,info b){
    43     if (a.a[0]>b.a[0]) return 1;
    44     if (a.a[0]<b.a[0]) return 0;
    45     for (int i=a.a[0];i;i--){
    46         if (a.a[i]>b.a[i]) return 1;
    47         if (a.a[i]<b.a[i]) return 0;
    48     }
    49     return 0;
    50 }
    51 int n,xx,yy;
    52 int main(){
    53     freopen("game.in","r",stdin);
    54     freopen("game.out","w",stdout);
    55     scanf("%d",&n);
    56     scanf("%d%d",&xx,&yy);
    57     for (int i=1;i<=n;i++) scanf("%d%d",&im[i].x,&im[i].y);
    58     sort(im+1,im+n+1,cmp);
    59     zero.a[0]=0;
    60     one.a[0]=one.a[1]=1;
    61     sum=one*xx;
    62     ans=zero;
    63     for (int i=1;i<=n;i++){
    64         save=sum/im[i].y;
    65         if (save>ans) ans=save;
    66         sum=sum*im[i].x;
    67     }
    68     ans.print();
    69 }
    View Code
  • 相关阅读:
    无法加载文件或程序集“System.Net.Http,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a”
    Linux中安装Oracle jdk
    算符优先文法,中缀式求值,栈的典型应用
    数据结构之--双链表MyLinkedList
    数据结构之--单链表MyArrayList
    Java中的函数对象
    (11)连个工具类之间的比较4.Collections与Arrays
    javaList容器中容易忽略的知识点
    (27)回复泛型,注解、日志组件、枚举在实际项目中的使用
    无问西东,哪怕重头来过
  • 原文地址:https://www.cnblogs.com/g-word/p/3371342.html
Copyright © 2011-2022 走看看