NOIP2012国王游戏

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


用贪心可以解决。


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


现给出证明:


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


两人左右手上的数字分别为l[1],r[1],l[2],r[2],令l[1]*r[1]


若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]


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


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


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


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


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


代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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.ls2.size();
    else
    {
        for(int i=0;is2[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=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>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<


你可能感兴趣的:(#,杂项算法)