话说要不是标签我都看不出来是个贪心。。
证明一下贪心
X X X的左手为 a 1 a_1 a1,右手为 b 1 b_1 b1。
Y Y Y的左手为 a 2 a_2 a2,右手为 b 2 b_2 b2
假设X位于Y的前边
位于 X X X前的大臣左手的乘积和 S 1 S_1 S1 | 位于 X X X前的大臣的右手的数为 M 1 M_1 M1 |
a 1 a_1 a1 | b 1 b_1 b1 |
这一段 ( a 1 ( a_1 (a1 到 a 2 ) a_2) a2)的左手乘积 S 2 S_2 S2 | Y Y Y前面大臣的右手的数 M 2 M_2 M2 |
a 2 a_2 a2 | b 2 b_2 b2 |
此时:
X X X所得的金币: S 1 b 1 \frac{S_1}{b_1} b1S1
Y Y Y所得的金币: S 1 a 1 S 2 b 2 \frac{S_1 a_1 S_2}{b_2} b2S1a1S2
则最小金币数为 m a x ( S 1 b 1 , S 1 a 1 S 2 b 2 ) max( \frac{S_1}{b_1},\frac{S_1 a_1 S_2}{b_2}) max(b1S1,b2S1a1S2)
将X和Y的位置调换
位于 Y Y Y前的大臣的左手乘积和 S 1 S_1 S1 | 位于 Y Y Y前的大臣的右手乘积和 M 1 M_1 M1 |
a 2 a_2 a2 | b 2 b_2 b2 |
这一段的左手乘积 S 2 S_2 S2 | X X X前面大臣的右手的数 M 2 M_2 M2 |
a 1 a_1 a1 | b 2 b_2 b2 |
此时:
Y
Y
Y所得的金币:
S
1
b
2
\frac{S_1}{b_2}
b2S1
X
X
X所得的金币:
S
1
a
2
S
2
b
1
\frac{S_1 a_2 S_2}{b_1}
b1S1a2S2
则最小金币数为 m a x ( S 1 b 2 , S 1 a 2 S 2 b 1 ) max( \frac{S_1}{b_2},\frac{S_1 a_2 S_2}{b_1}) max(b2S1,b1S1a2S2)
假设X在前优于Y在前
则
①:
m
a
x
(
S
1
b
1
,
S
1
a
1
S
2
b
2
max( \frac{S_1}{b_1},\frac{S_1a_1 S_2 }{b_2}
max(b1S1,b2S1a1S2
<
<
<
m
a
x
(
S
1
b
2
,
S
1
a
2
S
2
b
1
max( \frac{S_1}{b_2} , \frac{S_1 a_2 S_2}{b_1}
max(b2S1,b1S1a2S2恒成立
因为②:
S
1
b
1
<
=
S
1
a
2
S
2
b
1
\frac{S_1}{b_1}<= \frac{S_1a_2S_2}{b_1}
b1S1<=b1S1a2S2 恒成立
且 ③
S
1
b
2
<
=
S
1
a
1
S
2
b
2
\frac{S_1}{b_2}<= \frac{S_1a_1 S_2}{b_2}
b2S1<=b2S1a1S2恒成立
若要在②③基础上满足上述条件①则
首先要满足
S
1
a
1
S
2
b
2
<
\frac{S_1a_1S_2}{b_2} <
b2S1a1S2<
S
1
a
2
S
2
b
1
\frac{S_1a_2S_2}{b_1}
b1S1a2S2恒成立
即
a
1
b
1
<
a
2
b
2
a_1 b_1 < a_2 b_2
a1b1<a2b2
粗略说一下
在②③基础上,左边
m
a
x
max
max取
S
1
a
1
S
2
b
2
\frac{S_1 a_1 S_2} {b_2}
b2S1a1S2,右边取
S
1
a
2
S
2
b
1
\frac{S_1a_2S_2} {b_1}
b1S1a2S2才能使①成立
综上
我们需按照左右手乘积的排列大臣
补充
不考虑向下取整是因为:不考虑向下取整的最优解在向下取整的条件下不会比其余的解更劣
高精度
100%的数据范围要求使用高精乘除(不用luogu提交只有60pts)
Code
#include<bits/stdc++.h>
#define ll long long
#define maxn 10005
using namespace std;
int n;
int lena=1,lens=1,lenm=1;
int sum[maxn]={0,1},minn[maxn]={0,1},ans[maxn];
//sum用来存储每一位大臣前边大臣的左手数字乘积
//ans存储每个大臣对应的sum值除以右手的值
//minn存储最小的最大值 (即答案.....
struct node{
ll z,y;
}e[maxn];
bool cmp(node x,node y){
return x.z*x.y<y.z*y.y;
}
void cheng(ll x){
int num=0;
for(int i=1;i<=lens;i++){
sum[i]*=x;
}
for(int i=1;i<=lens;i++){
num+=sum[i];
sum[i]=num%10;
num/=10;
}
while(num){
lens++;
sum[lens]=num%10;
num/=10;
}
}
void chu(ll x){
memset(ans,0,sizeof(ans));
lena=lens;
int num=0;
for(int i=lena;i>=1;i--){
num*=10;
num+=sum[i];
if(num>=x){
ans[i]=num/x;
num%=x;
}
}
while(ans[lena]==0&&lena>1){//除去前导零
lena--;
}
}
void maxx(){
if(lena>lenm){
for(int i=1;i<=lena;i++){
minn[i]=ans[i];
}
lenm=lena;
}
else if(lena==lenm){
for(int i=lena;i>=1;i--){
if(minn[i]<ans[i]){
for(int j=1;j<=lena;j++){
minn[j]=ans[j];
}
break;
}
}
}
}
int main(){
scanf("%d",&n);
scanf("%d%d",&e[0].z,&e[0].y);
sum[1]=1;//初始为1才能存进数去
for(int i=1;i<=n;i++){
scanf("%d%d",&e[i].z,&e[i].y);
}
sort(e+1,e+n+1,cmp);
for(int i=1;i<=n;i++){
cheng(e[i-1].z);//乘
chu(e[i].y);//除
maxx();//取最大值
}
for(int i=lenm;i>=1;i--){
cout<<minn[i];
}
return 0;
}