P1080 [NOIP2012 提高组] 国王游戏

2 篇文章 0 订阅
1 篇文章 0 订阅

P1080 [NOIP2012 提高组] 国王游戏

这道题是一道邻接交换模型贪心加上高精度。

我们考虑位置 i i i 和位置 i + 1 i+1 i+1

t = ∏ j = 1 i − 1 a j t=\prod\limits_{j=1}^{i-1}a_j t=j=1i1aj

  1. 如果不交换:
    那么位置 i i i 和位置 i + 1 i+1 i+1 的可获得金币分别为:
    t b i , t ⋅ a i b i + 1 \frac{t}{b_i},\frac{t\cdot a_i}{b_{i+1}} bit,bi+1tai
    同时除以 t t t 再同时乘 b i b i + 1 b_ib_{i+1} bibi+1 变为:
    b i + 1 , a i b i b_{i+1},a_ib_i bi+1,aibi
  2. 如果交换:
    那么位置 i i i 和位置 i + 1 i+1 i+1 的可获得金币分别为:
    t b i + 1 , t ⋅ a i + 1 b i \frac{t}{b_{i+1}},\frac{t\cdot a_{i+1}}{b_i} bi+1t,bitai+1
    同时除以 t t t 再同时乘 b i b i + 1 b_ib_{i+1} bibi+1 变为:
    b i , a i + 1 b i + 1 b_i,a_{i+1}b_{i+1} bi,ai+1bi+1

然后我们就要比较 max ⁡ ( b i + 1 , a i b i ) \max(b_{i+1},a_ib_i) max(bi+1,aibi) max ⁡ ( b i , a i + 1 b i + 1 ) \max(b_i,a_{i+1}b_{i+1}) max(bi,ai+1bi+1) 那个小哪个大,如果交换小,就交换,反之不交换。

我们可以把式子写成 max ⁡ ( b i + 1 , a i b i ) < max ⁡ ( b i , a i + 1 b i + 1 ) \max(b_{i+1},a_ib_i)<\max(b_i,a_{i+1}b_{i+1}) max(bi+1,aibi)<max(bi,ai+1bi+1),当然我们可以再化简写成 a i b i < a i + 1 b i + 1 a_ib_i<a_{i+1}b_{i+1} aibi<ai+1bi+1 为什么,我们可以想一下极端数据如果 b i + 1 > a i b i b_{i+1}>a_ib_i bi+1>aibi 那么 b i + 1 b_{i+1} bi+1 肯定小于 a i + 1 b i + 1 a_{i+1}b_{i+1} ai+1bi+1 反之同理,所以可以化简。

代码:

#include <bits/stdc++.h>
#define x first
#define y second

using namespace std;

const int N = 1010;
typedef pair<int, int> pii;
int n; pii a[N];

namespace bignum {
	vector<int> convert(int x) {
		vector<int> t;
		do t.push_back(x % 10), x /= 10; while (x);
		return t;
	}

	void print(vector<int> t) {
		for (int i = t.size() - 1; i >= 0; --i)
			putchar(t[i] ^ 48);
		putchar('\n');
	}

	vector<int> mul(vector<int> a, int b) {
		vector<int> c; int t = 0;
		for (int i = 0; i < a.size() || t; ++i) {
			if (i < a.size()) t += a[i] * b;
			c.push_back(t % 10);
			t /= 10;
		}
		while (c.size() > 1 && c.back() == 0) c.pop_back();
		return c;
	}

	vector<int> div(vector<int> a, int b) {
		int r = 0; vector<int> c;
		for (int i = a.size() - 1; i >= 0; --i) {
			r = r * 10 + a[i];
			c.push_back(r / b);
			r %= b;
		}
		reverse(c.begin(), c.end());
		while (c.size() > 1 && c.back() == 0) c.pop_back();
		return c;
	}

	vector<int> maximum(vector<int> a, vector<int> b) {
		if (a.size() > b.size()) return a;
		else if (a.size() < b.size()) return b;
		else  {
			for (int i = a.size() - 1; i >= 0; --i) {
				if (a[i] > b[i]) return a;
				else if (a[i] < b[i]) return b;
			}
		}
		return a;
	}
}

bool cmp(pii a, pii b) {
	return a.x * a.y < b.x * b.y;
}

int main() {
	scanf("%d", &n);
	for (int i = 0; i <= n; ++i) {
		scanf("%d%d", &a[i].x, &a[i].y);
	}
	sort(a + 1, a + n + 1, cmp);
	// int res = 0, sum = a[0].x;
	vector<int> sum = bignum::convert(a[0].x), res;
	for (int i = 1; i <= n; ++i) {
		vector<int> t = bignum::div(sum, a[i].y);
		res = bignum::maximum(t, res);
		sum = bignum::mul(sum, a[i].x);
		// int t = sum / a[i].y;
		// res = max(res, t);
		// sum *= a[i].x;
	}
	bignum::print(res);
	// cout << res << endl;
	return 0;
}
  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值