洛谷P1080题解

关于数组排序的方式,摘个题解

假设已经排了几个人(包括国王),设他们左手上的数的乘积为SS。

现在要给22个人排序,记第一个人左手上的数为a_{1}a1​,右手上的数为b_{1}b1​;第二个人左手上的数为a_{2}a2​,右手上的数为b_{2}b2​。

如果第一个人排在前面优于第二个人排在前面,那么

max(S/b_{1},S*a_{1}/b_{2}) < max(S/b_{2},S*a_{2}/b_{2})max(S/b1​,S∗a1​/b2​)<max(S/b2​,S∗a2​/b2​)

而又由于a_{1},b_{1},a_{2},b_{2},S>0a1​,b1​,a2​,b2​,S>0,所以 S/b_{2} ≤ S*a_{1}/b_{2}S/b2​≤S∗a1​/b2​。

假设S*a_{1}/b_{2}≥S*a_{2}/b_{1}S∗a1​/b2​≥S∗a2​/b1​,则显然max(S/b_{1},S*a_{1}/b_{2})≥max(S/b_{2},S*a_{2}/b_{1})max(S/b1​,S∗a1​/b2​)≥max(S/b2​,S∗a2​/b1​),矛盾。

所以S*a_{1}/b_{2}<S*a_{2}/b_{1}=>a_{1}*b_{1}<a_{2}*b_{2}S∗a1​/b2​<S∗a2​/b1​=>a1​∗b1​<a2​∗b2​

只需将数组按照a*ba∗b从小到大排序即可。

此外,由于此题的数据范围较大,需要用到高精度计算

下面附上代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 10005;
struct ax
{
	int l, r;
}a[1005];
int x[M], y[M], z[M];//x用来存储连续相乘的结果,z用来存储答案,y用来表示每一个大臣的金币,通过与答案比较来确定是否更新答案
bool cmp(ax aa, ax bb)//排序
{
	return aa.l * aa.r < bb.l* bb.r;
}
void div(int* aa, int* bb, int num) //高精计算大臣金币
{
	memset(bb, 0, sizeof(bb));
	int x = 0;
	for (int i = M - 1; i >= 0; i--) {
		x = x * 10 + aa[i];
		bb[i] = x / num;
		x %= num;
	}
}
void copy(int* aa, int* bb)//复制函数,用来更新答案 {
	for (int i = 0; i < M; i++) aa[i] = bb[i];
}
bool more(int* aa, int* bb) //比较函数{
	for (int i = M - 1; i >= 0; i--) {
		if (aa[i] > bb[i]) return 1;
		if (aa[i] < bb[i]) return 0;
	}
	return 0;
}
void times(int* aa, int num) //高精度乘法{
	for (int i = M - 2; i >= 0; i--) aa[i] *= num;
	for (int i = 0; i < M - 1; i++) {
		aa[i + 1] += (aa[i] / 10);
		aa[i] %= 10;
	}
}

int main()
{
	int n;
	cin >> n;
	for (int i = 0; i <= n; i++)
		cin >> a[i].l >> a[i].r;
	sort(a + 1, a + n + 1, cmp)//对大臣进行排序;
	x[0] = 1;//初始化值为1
	for(int i = 0; i <= n; i++)
	{
		div(x, y, a[i].r)//先计算大臣的金币;
		if (more(y, z)) copy(z, y)//与答案比较后确认是否赋值;
		times(x, a[i].l)//继续相乘;
	}
	int k = 0;
	for (int i = M - 1; i >= 0; i--)//输出答案
	{
		if (k == 0)
		{
			if (z[i] == 0)
				continue;
			else
			{
				k = 1;
			}
		}
			cout << z[i];
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值