• [NOIP2012]国王游戏 -高精度-贪心-


    描述

    恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
    国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

    Solution

    贪心。左手的数用(l[i])表示,右手的数用(r[i])表示,只需以(l[i] * r[i])为关键字从小到大排序,求出奖赏最多的大臣所获的奖赏即可。

    但是为什么呢?

    可以考虑相邻的两个大臣(a_i和a_{i+1}),他们的奖赏分别为(左边为(a_i),右边为(a_{i+1}))

    (frac{1}{r[i]}*prodlimits_{k=0}^{i-1}l[k]和frac{1}{r[i+1]}*prodlimits_{k=0}^{i}l[k])

    交换位置后他们的奖赏为

    (frac{l[i + 1]}{r[i]}*prodlimits_{k=0}^{i-1}l[k]和frac{1}{r[i+1]}*prodlimits_{k=0}^{i-1}l[k])

    然后我们来比较

    (max(frac{1}{r[i+1]}*prodlimits_{k=0}^{i-1}l[k],frac{l[i]}{r[i]}*prodlimits_{k=0}^{i-1}l[k])和max(frac{1}{r[i]}*prodlimits_{k=0}^{i-1}l[k],frac{1}{r[i+1]}*prodlimits_{k=0}^{i}l[k]))

    同乘(frac{1}{r[i+1]*r[i]}*prodlimits_{k=0}^{i-1}l[k])

    即比较
    (\max(r[i + 1],l[i]*r[i])................1\max(r[i],r[i+1]*l[i+1])...............2)
    (\r[i+1] < r[i + 1]*l[i + 1]且r[i] < r[i] * l[i])

    (l[i]*r[i] < l[i+1]*r[i+1])时,(1)式小于(2)式,交换前更优,即把(l[i]*r[i])小的放在前面更优。

    #include<bits/stdc++.h>
    using namespace std;
    const int MOD = 10000;
    struct bint{
      int a[5000], len;
      int& operator [] (int x) { return a[x]; }
      bint():len(1){ memset(a, 0, sizeof(a));}
      bint(long long x) { memset(a, 0, sizeof(a)); len = 0; while(x) { a[++len] = x % MOD; x /= MOD; } }
      void print(){
        printf("%d", a[len]);
        for (int i = len - 1; i > 0; i--)
          printf("%04d", a[i]);
      }
    };
    bint operator * (bint& a,int b){
      int x = 0;
      for (int i = 1; i <= a.len; i++) 
        x += a[i] * b, a[i] = x % MOD, x /= MOD;
      if(x) a[++a.len] = x;
      return a;
    }
    bint operator / (bint& a,int b){
      bint c; c.len = a.len; int x = 0;
      for (int i = a.len; i > 0; i--) {
        x = x * MOD + a[i];
        c[i] = x / b;
        x %= b;
      }
      while(c[c.len] == 0 && c.len > 1) c.len--;
      return c;
    }
    bool operator < (bint& a,bint & b){
      if(a.len > b.len) return false;
      if(a.len < b.len) return true;
      for(int i = a.len; i >= 0; i--){
    		if(a[i] < b[i]) return true;
    		if(a[i] > b[i]) return false;
    	}
    	return false;
    }
    struct obj{
      int l, r, lr;
    }a[1010];
    bool cmp(obj a,obj b){
      return a.lr < b.lr;
    }
    int n;
    int main(){
      cin >> n;
      for (int i = 0; i <= n; i++){
        cin >> a[i].l >> a[i].r;
        a[i].lr = a[i].l * a[i].r;
      }
      sort(a + 1, a + n + 1, cmp);
      bint s(1),ans;
      
      for (int i = 1; i <= n; i++){
        if(a[i - 1].l == 0) break;
        s = s * a[i - 1].l;
        bint tmp;
        tmp = s / a[i].r;
        if(ans < tmp){
          ans = tmp;
        }
      }
      ans.print();
    }
    
  • 相关阅读:
    UNIX网络编程读书笔记:辅助数据
    使用Android Studio搭建Android集成开发环境(图文教程)
    Android数据存储(二)----PreferenceFragment详解
    Android系列----JUnit单元测试的使用
    Android数据存储(一)----SharedPreferences详解
    使用IntelliJ IDEA 13搭建Android集成开发环境(图文教程)
    Android系列之网络(三)----使用HttpClient发送HTTP请求(分别通过GET和POST方法发送数据)
    Android系列之网络(二)----HTTP请求头与响应头
    Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
    Android多线程----异步消息处理机制之Handler详解
  • 原文地址:https://www.cnblogs.com/FoxC/p/13546832.html
Copyright © 2020-2023  润新知