zoukankan      html  css  js  c++  java
  • NOIP2012 国王游戏

    传送门

    贪心还是很舒服的,不过加上高精度就很难受……

    我们要求的是得到金钱最多的大臣得到的钱数尽可能少。看到这个问题可能会想起二分答案之类的……不过看看这数据范围就知道不可能。想起之前做过一道类似的题,考虑一下贪心。

    直接贪心肯定是看不出来啥,那我们还是老套路,交换一下两个大臣。假设前面所有人乘积为w,第一个大臣左右手上的数为l1,r1,第二个为l2,r2.那么第一个大臣得到的钱就是w / r1,第二个是w * l1 / r2.交换之后,第一个大臣得到的是w / r2,第二个大臣得到的是w * l2 / r1,很显然我们只要比较w * l1 / r2和w * l2 / r1的大小即可。进行移项之后,发现w * l1 / r2 > w * l2 / r1的条件是l1 * r1 > l2 * r2.不过我们为了尽量让多的更少,所以我们肯定要逆着它来,把l,r乘积较大的大臣放在后面即可。

    之后就要上高精度了……好久没写高精度,这次补上了一发自己的高精度模板吧……只需要高精乘和高精除低精还是可以的。用重载运算符写题真爽

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 5005;
    const int N = 10000005;
     
    ll read()
    {
       ll ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9')
       {
          if(ch == '-') op = -1;
          ch = getchar();
       }
       while(ch >='0' && ch <= '9')
       {
          ans *= 10;
          ans += ch - '0';
          ch = getchar();
       }
       return ans * op;
    }
    
    struct dc
    {
       ll l,r;
       bool operator < (const dc &g) const
       {
          return l * r < g.l * g.r;
       }
    }c[M];
    
    struct big
    {
       int f[M],len;
       big()
       {
          memset(f,0,sizeof(f)),len = 0;
       }
       big change(int k)
       {
          big a;
          while(k) a.f[a.len++] = k % 10,k /= 10;
          while(!a.f[a.len] && a.len > 0) a.len--;
          return a;
       }
       void modi(int k)
       {
          while(k) f[len++] = k % 10,k /= 10;
          while(!f[len] && len > 0) len--;
       }
       big operator * (const big &g) const
       {
          big c;
          c.len = len + g.len + 1;
          //printf("!%d %d %d
    ",len,g.len,c.len);
          rep(i,0,len)
          rep(j,0,g.len)
          c.f[i+j] += f[i] * g.f[j];
          rep(i,0,c.len-1) c.f[i+1] += c.f[i] / 10,c.f[i] %= 10;
          while(!c.f[c.len] && c.len > 0) c.len--;
          return c;
       }
       big operator / (const int &g)
       {
          big c;
          int cur = 0;
          per(i,len,0) cur *= 10,cur += f[i],c.f[c.len++] = cur / g,cur %= g;
          reverse(c.f,c.f + c.len);
          while(!c.f[c.len] && c.len > 0) c.len--;
          return c;
       }
       void print()
       {
          per(i,len,0) printf("%d",f[i]);enter;
       }
    }kl,kr,ans;
    
    ll ka,kb,n;
    
    big bmax(const big &a,const big &b)
    {
       if(a.len != b.len) return a.len > b.len ? a : b;
       per(i,a.len,0)
       {
          if(a.f[i] == b.f[i]) continue;
          else return a.f[i] > b.f[i] ? a : b;
       }
       return a;
    }
    
    int main()
    {
       n = read();
       ka = read(),kb = read();
       kl.modi(ka),kr.modi(kb);
       //kl.print(),kr.print();
       rep(i,1,n) c[i].l = read(),c[i].r = read();
       sort(c+1,c+1+n);
       rep(i,1,n)
       {
          big L,R;
          L.modi(c[i].l);
          //L.print();putchar('#');
          big cur = kl / c[i].r;
          ans = bmax(ans,cur);
          kl = kl * L;
          //kl.print();
       }
       ans.print();
       return 0;
    }
  • 相关阅读:
    OC拨打电话
    oc唯一标时一部设备
    去掉UITableView多余的分割线
    UICollectionView的使用
    设置ulabel的行间距
    uitextfield
    iOS导航栏适配
    App Store 升级问题
    mac中使用终端生成RSA私钥和公钥文件
    js document
  • 原文地址:https://www.cnblogs.com/captain1/p/9873487.html
Copyright © 2011-2022 走看看