NC 16561 大数 + 贪心

题意

传送门 NC 16561

题解

考虑相邻的两个大臣,其交换顺序不会对其前面或后面的大臣获得的金币造成影响;假设大臣 i i i 排在大臣 j j j 前面时,这两个大臣获得的金币最大值最小,设排在前面的人左手数字乘积为 x x x,则有

m a x { x b i , x a i b j } ≤ m a x { x b j , x a j b i } max\{\frac{x}{b_{i}},\frac{xa_{i}}{b_{j}}\}\leq max\{\frac{x}{b_{j}},\frac{xa_{j}}{b_{i}}\} max{bix,bjxai}max{bjx,bixaj}

考虑到

x b i ≤ x a j b i   ,   x b j ≤ x a i b j \frac{x}{b_{i}}\leq \frac{xa_{j}}{b_{i}}\ ,\ \frac{x}{b_{j}}\leq \frac{xa_{i}}{b_{j}} bixbixaj , bjxbjxai

x b i ≥ x a i b j \frac{x}{b_{i}}\geq \frac{xa_{i}}{b_{j}} bixbjxai,满足条件;若 x b i < x a i b j \frac{x}{b_{i}}< \frac{xa_{i}}{b_{j}} bix<bjxai,则应满足

x a i b j ≤ x a j b i \frac{xa_{i}}{b_{j}}\leq\frac{xa_{j}}{b_{i}} bjxaibixaj

化简

a i b i ≤ a j b j a_{i}b_{i}\leq a_{j}b_{j} aibiajbj

以此对大臣排序,大数求金币最大值即可。测试点中存在脏数据,不能读入多组数据。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;

class bigInt
{
#define maxa 1005
#define base 10000
public:
    int limit;
    int arr[maxa];
    bigInt(int n)
    {
        memset(arr, 0, sizeof(arr));
        limit = 0;
        arr[limit] = n;
    }
    bigInt(const bigInt &a)
    {
        memset(arr, 0, sizeof(arr));
        limit = a.limit;
        for (int i = 0; i <= limit; i++)
            arr[i] = a.arr[i];
    }
    void operator*=(const int n)
    {
        int c = 0;
        for (int i = 0; i <= limit; i++)
        {
            arr[i] = arr[i] * n + c;
            if (arr[i] >= base)
            {
                c = arr[i] / base;
                arr[i] %= base;
                if (i == limit)
                {
                    ++limit;
                }
            }
            else
            {
                c = 0;
            }
        }
    }
    bigInt operator/(const int n)
    {
        bigInt a = bigInt(*this);
        for (int i = a.limit; i >= 0; i--)
        {
            if (a.arr[i] < n && i == a.limit && i > 0)
                --a.limit;
            if (i > 0)
                a.arr[i - 1] += a.arr[i] % n * base;
            a.arr[i] /= n;
        }
        return a;
    }
    friend bigInt mx(const bigInt &a, const bigInt &b)
    {
        if (a.limit != b.limit)
        {
            return a.limit > b.limit ? a : b;
        }
        for (int i = a.limit; i >= 0; i--)
        {
            if (a.arr[i] == b.arr[i])
                continue;
            return a.arr[i] > b.arr[i] ? a : b;
        }
        return a;
    }
    friend void output(const bigInt &a)
    {
        printf("%d", a.arr[a.limit]);
        for (int i = a.limit - 1; i >= 0; i--)
        {
            printf("%04d", a.arr[i]);
        }
        putchar('\n');
    }
};

#define maxn 1005
int a[maxn], b[maxn], r[maxn];

bool cmp(int i, int j)
{
    return a[i] * b[i] < a[j] * b[j];
}

int main()
{
    int n;
    scanf("%d", &n);
    int A, B;
    scanf("%d%d", &A, &B);
    for (int i = 0; i < n; i++)
    {
        r[i] = i;
        scanf("%d%d", a + i, b + i);
    }
    sort(r, r + n, cmp);
    bigInt f = bigInt(A), res = bigInt(0);
    for (int i = 0; i < n; i++)
    {
        res = mx(res, f / b[r[i]]);
        f *= a[r[i]];
    }
    output(res);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值