此篇文章的代码来自@Chlience,未经允许私自借用,十分不好意思。
题目链接:https://www.luogu.org/problemnew/show/P1080
拿到这个题目,我根本没有注意到数据范围竟然会超long long,真的是第一次做这种贪心题竟然需要写高精度。(做的题太少了,所以没见过,所以蒻)
首先推导一下贪心的策略:(借鉴自@Chlience)
简化一下问题,假如只有国王和两个大臣,总共三个人:如下图
king | a0 | b0 |
p1 | a1 | b1 |
p2 | a2 | b2 |
此时ans1 = max(a0/b1,(a0*a1)/b2)
king | a0 | b0 |
p2 | a2 | b2 |
p1 | a1 | b1 |
此时ans2 = max(a0/b2,(a0*a2)/b1)
显然可以化简为ans1 = max(k1,k2)
ans2 = max(k3,k4)
则有 k2>k3, k4>k1
若ans1<ans2
则 k4>k2
则 (a0*a2)/b1>(a0*a1)/b2
变换得:a1*b1<a2*b2
至此,我们得出了cmp()函数的写法。
然后,在此奉上@Chlience的代码:
#include <bits/stdc++.h>
using namespace std;
int now[20010],sum[20010],ans[20010],add[20010];
struct Node {
int a;
int b;
long long a_b;
}node[1010];
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 ;
}
int 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 0;
}
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.a_b<b.a_b;
}
int main() {
int n;
cin>>n;
for(int i=0;i<=n;i++) {
cin>>node[i].a>>node[i].b;
node[i].a_b=node[i].a*node[i].b;
}
sort(node+1,node+n+1,cmp);
ans[0]=1,ans[1]=1;
for(int i=1;i<=n;i++) {
times(node[i-1].a);
divition(node[i].b);
if(compare()) {
cp();
}
}
for(int i=sum[0];i>=1;i--)
printf("%d",sum[i]);
return 0;
}
自己还是太蒻了,高精度板子会写(抄),放在实际的应用里面就一团乱。