noip day1 2

ohac發表於2013-08-01

一道有點難的貪心(蒟蒻看法,神犇勿怪)

       首先可以發現,必然存在一種排列使最大值最小,現在我們假設得到了這個排列,任取其中兩個相鄰點,將其交換,結果必然不會更優,依據題目描述,在其前方的點的結果不會改變,後方也是一樣。設該店為i,i之前所有點之積為sumi,該位大臣得到金錢為pi,則有

pi=sumi/bi

p(i+1) = sum(i+1)/b(i+1) = sumi*ai/b(i+1) = pi*ai*bi/b(i+1)

由於b(i+1)為定值,可知若ai*bi最小,則p(i+1)最小,於是我們用ai*bi來排序,即可出解。

此題需用高精度。

下面附上程式碼(蒟蒻初學,不好勿怪):

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1010;
struct node
{
    long long x,y;
    bool operator <(node t)const {
        return x*y<t.x*t.y;
    }
}f[maxn];
struct ex //壓位高精
{
    int num[4*maxn];
    void operator *=(const int t) {
        int k=num[0];
        for(int i=1;i<=k;i++)
            num[i]*=t;
        for(int i=1;i<=k;i++) {
            num[i+1]+=num[i]/10000;
            num[i]%=10000;
        }
        k=num[0]+1;
        while(num[k]>0) {
            num[k+1]=num[k]/10000;
            num[k]%=10000;
            k++;
        }
        k--;
        if(num[0]<k) num[0]=k;
    }
    void operator /=(const int t) {
        int k=0;
        for(int i=num[0];i>=1;i--) {
            k=k*10000+num[i];
            num[i]=k/t;
            k%=t;
        }
        for(int i=2;i<=num[0];i++) {
            num[i-1]+=num[i]*10000;
            num[i]=num[i-1]/10000;
            num[i-1]%=10000;
        }
        k=num[0];
        while(num[k]==0) k--;
        num[0]=k;
    }
    bool cmp(ex t) const {
        if(num[0]!=t.num[0]) return num[0]<t.num[0];
        else {
            for(int i=num[0];i>=1;i--)
                if(num[i]!=t.num[i]) return num[i]<t.num[i];
        }
        return false;
    }
}res,ans;
int n;
long long a,b;
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%d",&n);
    cin>>a>>b;
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&f[i].x,&f[i].y);
    sort(&f[1],&f[n+1]); //按ai*bi排序
    memset(res.num,0,sizeof(res.num));
    memset(ans.num,0,sizeof(ans.num));
    ans.num[0]=1;
    res.num[0]=res.num[1]=1;
    res*=a;
    for(int i=1;i<=n;i++) {
        ex t=res;
        t/=f[i].y;
        if(ans.cmp(t)) ans=t;
        res*=f[i].x;
    }
    printf("%d",ans.num[ans.num[0]]);
    for(int i=ans.num[0]-1;i>=1;i--)
        printf("%04d",ans.num[i]);
    printf("\n");
    return 0;
}