题目描述
恰逢 HH 国国庆,国王邀请 nn 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 nn 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入输出格式
输入格式:第一行包含一个整数 nn ,表示大臣的人数。
第二行包含两个整数 aa 和 bb ,之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 nn 行,每行包含两个整数 aa 和 bb ,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式:一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
输入输出样例
说明
【输入输出样例说明】
按 11 、 22 、 33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22 ;
按 11 、 33 、 22 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22 ;
按 22 、 11 、 33 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22 ;
按 22 、 33 、 11 这样排列队伍,获得奖赏最多的大臣所获得金币数为 99 ;
按 33 、 11 、 22 这样排列队伍,获得奖赏最多的大臣所获得金币数为 22 ;
按 33 、 22 、 11 这样排列队伍,获得奖赏最多的大臣所获得金币数为 99 。
因此,奖赏最多的大臣最少获得 22 个金币,答案输出 22 。
【数据范围】
对于 20%的数据,有 1≤ n≤ 10,0 < a,b < 81≤n≤10,0<a,b<8 ;
对于 40%的数据,有 1≤ n≤20,0 < a,b < 81≤n≤20,0<a,b<8 ;
对于 60%的数据,有 1≤ n≤1001≤n≤100 ;
对于 60%的数据,保证答案不超过 10^9109 ;
对于 100%的数据,有 1 ≤ n ≤1,000,0 < a,b < 10000
1≤n≤1,000,0<a,b<10000
由题意可知其让我们求得一个队列,并且算出其中获得奖赏最多的大臣,所获奖赏尽可能少,且可知在排序后的有序队列中该大臣为队尾的大臣,所以题目转变为求满足一定要求的有序队列,该要求即为所获奖赏最多的人所获奖赏尽可能少。
设国王左手数为L[k],右手数为R[k],大臣左手数为L[i],大臣右手数为R[i],M[i]为第i位大臣拿到的奖赏数;(研究前两位大臣的情况)
大臣1与大臣2交换位置前:
M[1] = L[k] / R[1]
M[2] = (L[r] * L[1]) / R[2]
大臣1与大臣2交换位置后:
M[1] = (L[r] * L[2]) / R[1]
M[2] = L[k] / R[2]
则对于交换前可能大臣1奖赏数多或大臣2奖赏数多,交换后同理共4种情况
易得交换前大臣2奖赏数多,交换后大臣1奖赏数多可行有:
M[2] > M[1] ===> L[1] * R[1] > L[2] * R[2];
则易知针对于此情况应该进行交换,即将L[i] * R[i]结果小的往前放
注:此题应注意运算结果一溢出,应使用大数乘法与大数除法,且结果也应保存在数组中。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxCur 1000009
//kingGame流程,排序-〉大数乘-〉大数除
typedef struct stu{
int l,r;
} Person;
int cmp(const void *a,const void *b);
void mult(int pos);//乘法
void divi(int pos);//除法
Person courtiers[10000];//国王放在0位置
int op[maxCur],result[maxCur];
int heightCur = maxCur - 1,resultLowCur;
int main() {
int n,must = 0;
memset(courtiers,0,sizeof(courtiers));
scanf("%d",&n);
for(int i = 0; i <= n; i++)
scanf("%d %d",&courtiers[i].l,&courtiers[i].r);
qsort(&courtiers[1],n,sizeof(Person),cmp);
memset(op,0,sizeof(op));
memset(result,0,sizeof(result));
for(; courtiers[0].l; courtiers[0].l /= 10)
op[heightCur--] = courtiers[0].l % 10;
heightCur++;
for(int i = 1; i <= n; i++) {
if(i == n) {
divi(i);
break;
}
mult(i);
}
int i = 0;
for(; !result[i]; i++) ;
if(i >= resultLowCur) printf("1");
for(; i < resultLowCur; i++) printf("%d",result[i]);
return 0;
}
void divi(int pos) {
int cur = heightCur;
int tempNum = 0;
resultLowCur = 0;
for(; cur < maxCur; cur++,resultLowCur++) {
tempNum = tempNum * 10 + op[cur];
while(tempNum >= courtiers[pos].r) {
tempNum -= courtiers[pos].r;
result[resultLowCur]++;
}
}
}
void mult(int pos) {
int i;
for(i = maxCur - 1; i >= heightCur; i--)
op[i] *= (courtiers[pos].l);
for(i = maxCur - 1; i >= heightCur || op[i] >= 10; i--)
if (op[i] >= 10) {
op[i - 1] += (op[i] / 10);
op[i] %= 10;
}
if (op[i]) heightCur = i;
else heightCur = i + 1;
}
int cmp(const void *a,const void *b) {
Person* pa = (Person*) a;
Person* pb = (Person*) b;
return (pa->l * pa->r) - (pb->l * pb->r);
}