题解:P1080 [NOIP2012 提高组] 国王游戏

其实不用推那么多,邻项交换放弃大脑。

我直接在 cmp 中比较两者两种排序的权值,取较小的一种即可。

我令前面的乘积是 \(s\),则:

  1. 如果不换,那么权值是 \(\displaystyle \max(\frac{s}{r_1}, \frac{s \times l_1}{r_2})\)

  2. 如果换,那么权值是 \(\displaystyle \max(\frac{s}{r_2}, \frac{s \times l_2}{r_1})\)

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e3 + 5;



struct node {
	int l, r;
}a[N];

bool cmp(node a, node b) {
    return max(1.0 / (double)a.r, (double)a.l / b.r) < max(1.0 / (double)b.r, (double)b.l / a.r);
}

struct Num {
	int num[50005];
	int len;
	void init(int x) {
		while(x) {
			num[ ++ len] = x % 100000;
			x /= 100000;
		}
	}
	Num operator * (const int a) const {
		Num res;
		for(int i = 1;i <= len;i ++ ) {
			res.num[i] = a * num[i];
		}
		for(int i = 1;i <= len;i ++ ) {
			res.num[i + 1] += res.num[i] / 100000;
			res.num[i] %= 100000;
		}
		res.len = len;
		while(res.num[res.len + 1] != 0) {
			res.num[res.len + 1] += res.num[res.len] / 100000;
			res.num[res.len] %= 100000;
			res.len ++ ;
		}
		return res;
	}
	Num operator / (const int a) const {
		Num res;
		long long cur = 0;
		for(int i = len;i >= 1;i -- ) {
			cur = cur * 100000 + num[i];
			res.num[i] = cur / a;
			cur %= a;
		}
		res.len = len;
		while(res.num[res.len] == 0) res.len -- ;
		return res;
	} 
	bool operator < (const Num a) const {
		if(len > a.len) return 0;
		if(len < a.len) return 1;
		for(int i = len;i >= 1;i -- ) {
			if(num[i] > a.num[i]) return 0;
			if(num[i] < a.num[i]) return 1; 
		}
		return 1;
	}

};

	
int main() {
	int n, x, y;
	cin >> n;
	cin >> x >> y;
	for(int i = 1;i <= n;i ++ ) {
		cin >> a[i].l >> a[i].r;
	}
	/*
	相邻的两个大臣 l1, r1, l2, r2, 令前面的乘积为 s
	max(1 / r1, l1 / r2), max(1 / r2, l2 / r1)
	如果不交换是最优的, 则
	1. 1 / r1 < 1 / r2	
		则 1 / r2 > l2 / r1
		又 l2 / r1 > 1 / r1
		则 1 / r2 > 1 / r1	恒成立 
	2. 1 / r1 < l2 / r1  	恒成立
	3. l1 / r2 < 1 / r2		无解(不可能出现) 
	4. l1 / r2 < l2 / r1
	*/
	sort(a + 1, a + n + 1, cmp);
	Num ans, cur;
	ans.init(0);
	cur.init(x);
	for(int i = 1;i <= n;i ++ ) {
		ans = max(ans, cur / a[i].r);
		cur = cur * a[i].l;
	}
	printf("%d", ans.num[ans.len]);
	for(int i = ans.len - 1;i >= 1;i -- ) {
		printf("%05d", ans.num[i]);
	}
	return 0;
}
posted @ 2025-09-16 19:48  yanbinmu  阅读(5)  评论(0)    收藏  举报