题解:本题主要考查贪心+高精度
简要题意:有
n
n
n位大臣,左手右手分别写一个数,国王也写。排成一排,国王站最前面。每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。求奖赏最多的大臣,所获奖赏尽可能的少。
1.贪心:本题的贪心很巧妙,我们可以从小规模的数据入手。
kin:
n
1
,
n
2
n_1,n_2
n1,n2
p1:
x
1
,
y
1
x_1,y_1
x1,y1
p2:
x
2
,
y
2
x_2,y_2
x2,y2
得出答案:
a
n
s
1
=
m
a
x
(
n
1
÷
y
1
,
n
1
×
x
1
÷
y
2
)
;
ans1=max(n_1 \div\ y_1,n_1 \times\ x_1 \div\ y_2 );
ans1=max(n1÷ y1,n1× x1÷ y2);
如果我们交换p1 p2的位置
kin:
n
1
,
n
2
n_1,n_2
n1,n2
p2:
x
2
,
y
2
x_2,y_2
x2,y2
p1:
x
1
,
y
1
x_1,y_1
x1,y1
a
n
s
2
=
m
a
x
(
n
1
÷
y
2
,
n
1
×
x
2
÷
y
1
)
;
ans2=max(n_1 \div\ y_2,n_1 \times\ x_2 \div\ y_1 );
ans2=max(n1÷ y2,n1× x2÷ y1);
那么如果
a
n
s
1
<
a
n
s
2
ans1<ans2
ans1<ans2 那么易得:
n
1
×
x
2
÷
y
1
<
n
1
×
x
1
÷
y
2
;
n_1 \times\ x_2 \div\ y_1<n_1 \times\ x_1 \div\ y_2;
n1× x2÷ y1<n1× x1÷ y2;
所以得:
x
1
×
y
1
<
x
2
×
y
2
;
x_1 \times\ y_1<x_2 \times\ y_2;
x1× y1<x2× y2;
那么我们以
x
i
∗
y
i
x_i*y_i
xi∗yi为关键字排序即可。
2.高精度:统计答案要写高精度。
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Node
{
int l;
int r;
long long ab;
}coin[1010];
int now[20010],sum[20010],ans[20010],add[20010];
int n;
void times(int x) //高精度加法
{
memset(add,0,sizeof(add));
for(int i=1;i<=ans[0];i++)
{
ans[i]=ans[i]*x;
add[i+1]+=ans[i]/10;
ans[i]%=10;
}
for(int i=1;i<=ans[0]+4;i++)
{
ans[i]+=add[i];
if(ans[i]>=10)
{
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
if(ans[i]!=0)ans[0]=max(ans[0],i);
}
return ;
}
void divition(int x) //高精度除法
{
memset(add,0,sizeof(add));
int q=0;
for(int i=ans[0];i>=1;i--)
{
q*=10;
q+=ans[i];
add[i]=q/x;
if(add[0]==0 && add[i]!=0)add[0]=i;
q%=x;
}
return ;
}
bool compare()
{
if(sum[0]==add[0])
for(int i=add[0];i>=1;i--)
{
if(add[i]>sum[i])return 1;
if(add[i]<sum[i])return 0;
}
if(add[0]>sum[0])return 1;
if(add[0]<sum[0])return 0;
}
void cp()
{
memset(sum,0,sizeof(sum));
for(int i=add[0];i>=0;i--)
sum[i]=add[i];
return ;
}
bool cmp(Node a,Node b)
{
return a.ab<b.ab;
}
int main()
{
cin>>n;
for(int i=0;i<=n;i++)
{
cin>>coin[i].l>>coin[i].r;
coin[i].ab=coin[i].l*coin[i].r;
}
sort(coin+1,coin+n+1,cmp);
ans[0]=1,ans[1]=1;
for(int i=1;i<=n;i++)
{
times(coin[i-1].l);
divition(coin[i].r);
if(compare())cp();
}
for(int i=sum[0];i>=1;i--)cout<<sum[i];
return 0;
}