关于数组排序的方式,摘个题解
假设已经排了几个人(包括国王),设他们左手上的数的乘积为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];
}
}