NOIP 2012 国王游戏 贪心 高精度 (COGS 1263)

T^T,太桑心了,自己搞了好长时间的高精度,当最终搞出来没问题的高精度之后,就来写这道题了。却不曾想到自己倍增式的低级高精除T掉了。T^T……
还是再好好搞搞高精除吧。。。

来说这道题的贪心思路,又是一个与顺序相关的,不过与上一次写的那个矩形分割不同,这个并不是很容易能看出来或想出来,需要写一写。

假设一个最佳序列a1,a2,a3,a4……i,j……an。
设k = l[a1]*l[a2]*l[a3]*……*l[i-1];
考虑对于任意1 <= i < n (j == i+1),交换i和j的位置,因为之前是最优的,那么交换i,j后一定不如之前的优,即有:k*l[i]/r[i] <= k*l[j]/r[i],稍微变形即有l[i]*r[i] <= l[j]*r[j],即l[i]*r[i] <= l[i+1]*r[i+1]。

那么就有了贪心的依据:l[i]*r[i]的升序排列是“最优”的排列。为什么加引号呢?因为这个最优是一个特殊的概念,因为我们保持的是每组i,i+1都满足这个条件,而改变其中一些可能不会影响最大值,就像样例中有好多种排序方式都得到2的结果一样。

不过我们只需要最后结果正确就好了,不要太在意这个。
然而自己并没有AC,因为渣渣一样的高精度。。。暂时没有代码。T^T.

过了10min后AC啦,自己写的高精除高精太慢。。于是改成了高精除单精,模拟竖式还是很快的。

不过注意这道题最多大概会出现5000位数,高精度的数组不要开小了。

#include 
#include 
#include 
#define M 1005
#define P 10000
using namespace std;

int n;
char s[M];

struct BigInt{
    int a[M], h;
    bool neg;

    BigInt(){
        h = neg = 0;
        memset(a, 0, sizeof a);
    }

    void read(){
        memset(s, 0, sizeof s);
        scanf("%s", s+1);
        int len = strlen(s+1);
        h = 1;
        for(int i = len, j = 1; i; i--, j *= 10){
            if(j == P){
                j = 1;
                h++;
            }
            a[h] += (s[i]-'0')*j;
        }
    }

    void read(char *s){
        int len = strlen(s);
        h = 1;
        for(int i = len-1, j = 1; i >= 0; i--, j *= 10){
            if(j == P){
                j = 1;
                h++;
            }
            a[h] += (s[i]-'0')*j;
        }
    }

    bool operator < (BigInt k) const {
        if(h > k.h) return 0;
        if(h < k.h) return 1;
        for(int i = h; i; i--){
            if(a[i] > k.a[i]){
                return 0;
            }
            if(a[i] < k.a[i]){
                return 1;
            }
        }
        return 0;
    }

    bool operator > (BigInt k) const {
        if(h > k.h) return 1;
        if(h < k.h) return 0;
        for(int i = h; i; i--){
            if(a[i] > k.a[i]){
                return 1;
            }
            if(a[i] < k.a[i]){
                return 0;
            }
        }
        return 0;
    }

    bool operator == (BigInt k) const {
        if(h != k.h) return 0;
        for(int i = h; i; i--){
            if(a[i] != k.a[i]) return 0;
        }
        return 1;
    }

    BigInt operator + (BigInt k) const {
        BigInt res = *this;
        res.h = max(res.h, k.h);
        for(int i = 1; i <= res.h; i++){
            res.a[i] += k.a[i];
            res.a[i+1] += res.a[i] / P;
            res.a[i] %= P;
        }
        while(res.a[res.h+1]) res.h++;
        return res;
    }

    BigInt operator - (BigInt k) const {
        BigInt res = *this;
        for(int i = 1; i <= k.h; i++){
            res.a[i] -= k.a[i];
            if(res.a[i] < 0){
                res.a[i] += P;
                res.a[i-1]--;
            }
        }
        return res;
    }

    BigInt operator * (BigInt k) const {
        BigInt res;
        if(!h || !k.h) return res; 
        for(int i = 1; i <= h; i++)
        for(int j = 1; j <= k.h; j++){
            res.a[i+j-1] += a[i] * k.a[j];
            res.a[i+j] += res.a[i+j-1] / P;
            res.a[i+j-1] %= P;
        }
        res.h = h + k.h + 2; 
        while(!res.a[res.h] && res.h) res.h--; 
        return res;
    }

    BigInt operator * (int k) const {
        BigInt res;
        if(!h || !k) return res; 
        for(int i = 1; i <= h; i++){
            res.a[i] += a[i] * k;
            res.a[i+1] += res.a[i] / P;
            res.a[i] %= P;
        }
        res.h = h + 2; 
        while(!res.a[res.h] && res.h) res.h--; 
        return res;
    }

    BigInt operator / (BigInt k) const {
        BigInt res, two;
        int cha = h - k.h;
        if(cha > 1){
            cha--;
            res.h = 1;
            res.a[2] = cha;
            res.a[1] = cha * P % P;
            while(res.a[res.h+1]){
                res.h++;
                res.a[res.h+1] += res.a[h] / P;
                res.a[h] %= P;
            }
        }
        two.h = 1;
        two.a[1] = 2;
        #define RES k*res+k
        while(RES < *this || RES == *this){
            BigInt t;
            t.h = t.a[1] = 1;
            while(k*(t+res)*two < *this || k*(t+res)*two == *this){
                t = t * two;
            }   
            res = res + t;
        }
        return res;
    }

    BigInt operator / (int k) const {  
        BigInt res;
        int x = 0;
        for(int i = h; i; i--){  
            res.a[i] = (x*P + a[i]) / k;
            x = (x*P + a[i]) % k;
        }
        res.h = h;
        while(!res.a[res.h] && res.h) res.h--;  
        return res;
    }

    void print(){
        if(!h) {                 
            printf("0");
            return; 
        }
        if(neg) printf("-");
        printf("%d", a[h]);
        for(int i = h-1; i; i--){
            int k = a[i], len = 1;
            while(k){
                len *= 10;
                k /= 10;
            }
            if(len==1) len *= 10; 
            while(len < P){
                printf("0");
                len *= 10;
            }
            printf("%d", a[i]);
        }
    }
}l, r, k, ans;

struct peo{
    BigInt l, w;
    int r;
    bool operator < (peo k) const {
        return w < k.w;
    }
}p[1005];

int main()
{
    scanf("%d", &n);
    l.read();
    r.read();
    for(int i = 1; i <= n; i++){
        p[i].l.read();
        scanf("%d", &p[i].r);
        p[i].w = p[i].l * p[i].r;
    }
    sort(p+1, p+n+1);

    k = l;
    for(int i = 1; i <= n; i++){
        ans = max(ans, k/p[i].r);
        k = k * p[i].l;
    }
    ans.print();
    return 0;
}

你可能感兴趣的:(NOIP 2012 国王游戏 贪心 高精度 (COGS 1263))