洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度

Posted Zinn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度相关的知识,希望对你有一定的参考价值。

题目:https://www.luogu.org/problemnew/show/P1080

排序方法的确定,只需任取两个人,通过比较与推导,可以得出ai*bi小的人排在前面;

高精度写的时候犯了些细节错误,详见注释。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 200005
using namespace std;
typedef long long ll;//用long long! 
ll n,ka,kb,ans[MAXN],tmp[MAXN],tmp2[MAXN],c[MAXN];
struct N{
    ll a,b;
}p[1005];
bool cmp(N x,N y)
{
    return x.a*x.b<y.a*y.b;
}
void chu(ll a[],ll b)
{
    ll x=0;
    c[0]=a[0];
    for(ll i=a[0];i>0;i--)//倒序存储,正序除 
    {
        c[i]=(x*10000+a[i])/b;
        x=(x*10000+a[i])%b;
    }
    while(c[c[0]]==0&&c[0]>0)c[0]--;
}
void ch(ll a[],ll b)
{
    ll x=0;
    for(ll i=1;i<=a[0];i++)//倒序乘 
    {
        a[i]*=b;a[i]+=x;
        x=a[i]/10000;
        a[i]%=10000;
    }
    while(x)a[0]++,a[a[0]]=x%10000,x/=10000;
}
int com(ll a[],ll b[])
{
    if(a[0]>b[0])return 1;
    if(a[0]<b[0])return -1;
    for(ll i=a[0];i;i--)//倒序! 
        if(a[i]>b[i])return 1;
    return 0;
}
void print(ll a[])
{
//    if(a[a[0]]==0)//?
//    {
//        printf("1");
//        return;
//    }
    printf("%lld",a[a[0]]);
    for(ll i=a[0]-1;i>0;i--)
    {
        printf("%lld",a[i]/1000);
        a[i]%=1000;
        printf("%lld",a[i]/100);
        a[i]%=100;
        printf("%lld",a[i]/10);
        a[i]%=10;
        printf("%lld",a[i]);
    }
}
int main()
{
    scanf("%lld%lld%lld",&n,&ka,&kb);
    for(ll i=1;i<=n;i++)
        scanf("%d%d",&p[i].a,&p[i].b);
    sort(p+1,p+n+1,cmp);
    tmp[0]=1;tmp[1]=ka;//压位 
    for(ll i=1;i<=n;i++)
    {
        memcpy(tmp2,tmp,sizeof tmp);
        memset(c,0,sizeof c);
        chu(tmp2,p[i].b);
        if(com(c,ans)>0)memcpy(ans,c,sizeof c);//必须>0,否则-1也会被算! 
        ch(tmp,p[i].a);
    }
    print(ans);
    return 0;
}

这个运行起来有点慢,有些地方写得不够好,下面有一篇运行很快的代码,可以比较看看提速的方法。

技术分享图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=10000;
typedef long long ll;
ll n,gb,ljc[1005],max,tmp[1005],ans[1005];
char tp[5];
struct Node{
    ll a,b,w;
}r[1005];
bool cmp(Node x,Node y)
{
    return x.w<y.w;
}
void chu(ll b)
{
    ll x=0;
    tmp[0]=ljc[0];
    for(ll i=ljc[0];i;i--)
    {
        ll s=ljc[i]+x*INF;
        tmp[i]=s/b;
        x=s%b;
    }
    while(!tmp[tmp[0]]&&tmp[0]>1)tmp[0]--;
}
bool comp(ll ans[],ll b[])
{
    if(ans[0]>b[0])return 0;
    if(ans[0]<b[0])return 1;
    for(ll i=ans[0];i;i--)
    {
        if(ans[i]>b[i])return 0;
        if(ans[i]<b[i])return 1;
    }
    return 0;
}
void mul(ll a)
{
    ll x=0;
    for(ll i=1;i<=ljc[0];i++)
    {
        ll s=ljc[i]*a+x;
        x=s/INF;
        ljc[i]=s%INF;
    }
    if(x)ljc[0]++,ljc[ljc[0]]=x;//至多进一位 
}
int main()
{
    scanf("%lld%lld%lld",&n,&ljc[1],&gb);
    ljc[0]=1;
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld%lld",&r[i].a,&r[i].b);
        r[i].w=r[i].a*r[i].b;
    }
    sort(r+1,r+n+1,cmp);
    for(ll i=1;i<=n;i++)
    {
        memset(tmp,0,sizeof tmp);
        chu(r[i].b);
        if(comp(ans,tmp))memcpy(ans,tmp,sizeof tmp);
        mul(r[i].a);
    }
    printf("%lld",ans[ans[0]]);
    for(ll i=ans[0]-1;i;i--)
    {
        printf("%lld",ans[i]/1000);
        printf("%lld",ans[i]/100%10);
        printf("%lld",ans[i]/10%10);
        printf("%lld",ans[i]%10);
    }
    return 0;
}
View Code

 

以上是关于洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1080 [NOIP2012提高组D1T2]国王游戏 [2017年5月计划 清北学堂51精英班Day1]

洛谷P1080 国王游戏 高精度 贪心 数学推公式

国王游戏 2012年NOIP全国联赛提高组(贪心+高精)

AC日记——国王游戏 洛谷 P1080

[NOIP2012提高组]国王旅行

洛谷P1080 国王游戏