【NOIP2012提高组】国王游戏 贪心 + 高精度

题目分析

题目答案不具有单调性,所以不可以二分,转而思考贪心。因为无法确定位置,所以考虑如何才能让对于每一个$1 ~ i$使得$i$的答案最大,即$1 ~ i$最后一个最优。若设对于位置$i$,$a[i]$表示左手,$b[i]$表示右手,$S$为其前面所有人的左手之积,那么他的答案就是$\frac{S}{b[i]}$,如果存在在$i$后边的$j$的答案更优, 即$\frac{S * a[i]}{b[j]} > \frac{S * a[j]}{b[i]} => a[i] * b[i] > a[j] * b[j]$,这样只要我们以a[i] * b[i]为关键字从小到大排序,就能保证每个前缀的最后一个都是最优的,只要$o(n)$扫一遍取最大值即可,记得使用高精度。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

const int N = 1050;
int n, a[N], b[N], c[N], ka, kb, kc;

inline int read(){
    int i = 0, f = 1; char ch = getchar();
    for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
    if(ch == '-') f = -1, ch = getchar();
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        i = (i << 3) + (i << 1) + (ch - '0');
    return i * f;
}

inline void wr(int x){
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) wr(x / 10);
    putchar(x % 10 + '0');
}

struct bign{
    int len, s[10000];
    bign():len(0){memset(s, 0, sizeof s);}
    bign(int x):len(0){
        memset(s, 0, sizeof s);
        while(x){
            s[++len] = x % 10;
            x /= 10;
        }
        if(!len) len = 1;
    }
    inline void clear(){
        while(len > 1 && s[len] == 0) len--;
    }
    inline bign operator * (const bign &b) const{
        bign ret;
        ret.len = len + b.len + 5;
        for(int i = 1; i <= len; i++)
            for(int j = 1; j <= b.len; j++)
                ret.s[i + j - 1] += s[i] * b.s[j];
        for(int i = 1; i <= ret.len; i++)
            if(ret.s[i] >= 10){
                ret.s[i + 1] += ret.s[i] / 10;
                ret.s[i] %= 10;
            }
        ret.clear();
        return ret;
    }
    inline bign operator - (const bign &b) const{
        bign ret;
        ret.len = len;
        for(int i = 1; i <= len; i++){
            ret.s[i] = ret.s[i] + s[i];
            if(i <= b.len) ret.s[i] = ret.s[i] - b.s[i];
            if(ret.s[i] < 0){
                ret.s[i + 1]--;
                ret.s[i] += 10;
            }
        }
        ret.clear();
        return ret;
    }
    bign operator / (int b) {
        bign c;
        int f = 0;
        for(int i = len; i >= 1; i--){
            f = f * 10 + s[i];
            while(!(f < b)){
                f -= b;
                c.s[i]++;
            }
        }
        c.len = len;
        c.clear();
        return c;
    }
    inline bool operator > (const bign &b) const{
        if(len != b.len) return len > b.len;
        for(int i = len; i >= 1; i--)
            if(s[i] != b.s[i]) return s[i] > b.s[i];
        return false;
    }
    inline bool operator == (const bign &b) const{
        if(len != b.len) return false;
        for(int i = len; i >= 1; i--)
            if(s[i] != b.s[i]) return false;
        return true;
    }
    inline bool operator < (const bign &b) const{
        if(len != b.len) return len < b.len;
        for(int i = len; i >= 1; i--)
            if(s[i] != b.s[i]) return s[i] < b.s[i];
        return false;
    }
    inline void print(){
        for(int i = len; i >= 1; i--)
            wr(s[i]);
    }
}fa, ans, big0, big10;

struct node{
    int a, b, c;
    inline bool operator < (const node &u) const{
        if(c != u.c) return c < u.c;
        return b > u.b;
    }
}data[N];

int main(){
    n = read(), ka = read(), kb = read();
    for(int i = 1; i<= n; i++){
        data[i].a = read(), data[i].b = read();
        data[i].c = data[i].a * data[i].b;
    }
    sort(data + 1, data + n + 1);
    fa = ka;
    ans = 0;
    bign tmpa, t;
    for(int i = 1; i <= n; i++){
        tmpa = data[i].a;
        t = fa / data[i].b;
        if(t > ans) ans = t;
        fa = fa * tmpa;
    }
    ans.print();
    return 0;
}
posted @ 2017-08-25 20:08  CzYoL  阅读(292)  评论(0编辑  收藏  举报