NOIP2012国王游戏

来源:互联网 发布:重庆seo网站诊断 编辑:程序博客网 时间:2024/04/30 23:34

题目来源:https://www.luogu.org/problem/show?pid=1080


用贪心可以解决。


将所有人按左右手的乘积排序,这样一定可以保证结果最优。


现给出证明:


首先,任意相邻两人的顺序对于排在他们前面和后面的人没有影响。(显然)


两人左右手上的数字分别为l[1],r[1],l[2],r[2],令l[1]*r[1]<l[2]*r[2],排在他们前面的所有人左手上的乘积为sum。


若1在2前面,那么两人分得的金币分别为sum/r[1],sum*l[1]/r[2]。


若2在1前面,两人分得的金币分别为sum/r[2],sum*l[2]/r[1]。


现比较max(sum/r[1],sum*l[1]/r[2])和max(sum/r[2],sum*l[2]/r[1])的大小:


因为l[1]*r[1]<l[2]*r[2],故max(sum/r[2],sum*l[2]/r[1])=sum*l[2]/r[1]。


而sum*l[2]/r[1]>sum/r[1]显然成立且sum*l[2]/r[1]>sum*l[1]/r[2]也成立(因为l[1]*r[1]<l[2]*r[2])。


故max(sum/r[1],sum*l[1]/r[2])<max(sum/r[2],sum*l[2]/r[1])。


故1在2前面两人分得的金币的最大值最小。


以此类推,左右手乘积较大的放在后面结果会更优。证毕。


由于此题数据较大,需要用到高精度乘法和除法。


代码:


#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <sstream>#include <cstdio>#include <string>#include <vector>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <set>#include <map>using namespace std;struct node{long long l,r;}c[100010];long long a[100010],b[100010];int n;bool cmp(node a,node b){return a.r*a.l<b.r*b.l;}bool comp(string s1,string s2){    if(s1.size()!=s2.size())return s1.size()>s2.size();    else    {        for(int i=0;i<s1.size();i++)        {            if(s1[i]!=s2[i])return s1[i]>s2[i];        }    }    return 0;}string milt(string s,long long t){    long long ans[10001]={0};    long long u[10001]={0};    for(int i=0;i<s.size();i++)u[s.size()-i]=s[i]-'0';    for(int i=1;i<s.size()+16;i++)    {        ans[i]+=u[i]*t;        if(ans[i]>=10)ans[i+1]=ans[i]/10;        ans[i]%=10;    }    string e;    int v=s.size()+16;    while(v>1&&ans[v]==0)v--;    for(int i=v;i>=1;i--)e+=(ans[i]+'0');    return e;}string chu(string s,long long t){    string e;    long long g=0,p=0;    while(g<t&&p<s.size())    {        g=g*10+s[p]-'0';        p++;    }    e+=(g/t+'0');g%=t;    for(int i=p;i<s.size();i++)    {        g=g*10+s[i]-'0';        e+=(g/t+'0');g%=t;    }    if(e.size()==0)e='0';    return e;}int main(){    cin>>n;    for(int i=0;i<=n;i++)    {        cin>>a[i]>>b[i];        c[i].l=a[i];        c[i].r=b[i];    }    sort(c+1,c+n+1,cmp);    string sum="1";    string tot="0";    for(int i=0;i<=n;i++)    {        string u=chu(sum,c[i].r);        if(comp(u,tot))tot=u;        sum=milt(sum,c[i].l);    }    cout<<tot;    return 0;}


0 0
原创粉丝点击