[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]}*\prod\limits_{k=0}^{i-1}l[k]和\frac{1}{r[i+1]}*\prod\limits_{k=0}^{i}l[k]\)

交换位置后他们的奖赏为

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

然后我们来比较

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

同乘\(\frac{1}{r[i+1]*r[i]}*\prod\limits_{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();
}
posted @ 2020-08-22 19:33  foxc  阅读(124)  评论(0编辑  收藏  举报