CSU 2257 Intergalactic Bidding 超递增背包+大数

http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2257

Description

Today the Intergalactic Council of Pebble Coins (ICPC) conducted an intergalactic auction of the Neutronium Chaos Pebble Coin (NCPC). This coin, which was forged in the Ancient Coin Machine (ACM), is rumored to be the key to ruling the universe.

Due to the extremely competitive nature of the auction, as well as the odd mechanics of the intergalactic currency used (far too advanced for mere mortals to understand), the auction was conducted with the following rules:

  1. only one participant was allowed to make a bid at a time,

  2. each participant was only allowed to make one bid, and

  3. a participant making a bid had to bid at least twice the amount of the highest bid at the time.

The first participant making a bid was allowed to make a bid of any positive amount.

After the auction there were a lot of sore losers -- understandably, having just lost their chance at world domination. To make the losers feel a little better and prevent possible rioting, the ICPC has decided to hold a lottery for the participants. The winners of the lottery are determined as follows. The ICPC picks a random number s. A group of participants is called winning if the sum of their bets from the auction is equal to s. A participant wins the lottery and receives a prize -- a shiny Pebble Coin -- if they belong to any winning group of participants.

Given the names of the participants, the bets that they made, and the random number s chosen by the ICPC, help them determine which participants won the lottery.

Input

The first line of input contains two integers n and s, where 1 ≤ n ≤ 1 000 is the number of participants, and 1 ≤ s < 101 000 is the random number chosen by the ICPC.

Then follow n lines describing the participants. Each line contains a string t and an integer b, where t is the name of a participant, and 1 ≤ b < 101 000 is the amount of his bet. The name of each participant is unique and consists of between 1 and 20 letters from the English alphabet.

Output

Output an integer k denoting the number of participants that won the lottery. Then output k​ lines containing the names of the participants that won the lottery, one per line, in any order.

Sample Input

5 63
Vader 3
Voldemort 7
BorgQueen 20
Terminator 40
Megatron 101
---------------------------
4 1112
Blorg 10
Glorg 1000
Klorg 1
Zlorg 100

Sample Output

3
BorgQueen
Terminator
Vader
---------------------
0

Hint

Source

题目大意:给出n个人的名字及其下注的金额,以及最终的拍卖价格,每个人只能下注1次且当前人下注的金额必须>=场上最高下注金额的两倍,第一个人可任意起价,问能否找到一组下注金额使得它们的和等于最终拍卖价格。

思路:我们来看一下最极限的情况:t 2t 4t 8t……我们可以发现这个序列满足:

\sum_{1}^{i-1}ai<aj

满足这个性质的序列又称为超递增序列,超递增背包差不多也是这个意思。密码学中学到过,大数背包问题是难解的,但是超递增背包是易解的,O(n)扫一遍即可得到答案。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <cctype>
using namespace std;
typedef long long LL;

struct BigInteger {
    static const int D = 10000;
    typedef vector<int> DigSet;

    enum Sign {positive, negative} sign;
    DigSet dig;
    BigInteger(const DigSet& dig = DigSet(), Sign sign = positive):sign(sign),dig(dig){}
    BigInteger(LL val):sign(val>=0?positive:negative) {
        val = abs(val);
        while (val) {
            dig.push_back(val%D);
            val /= D;
        }
    }
    BigInteger(const string& val) {
        for (int i = val.size() - 1; i >= 0; i-=4) {
            int d = 0;
            for (int j = 0, p=1; j < 4 && i - j >= 0 && isdigit(val[i - j]); j++, p*=10) {
                d += (val[i-j] & 0xf)*p;
            }
            dig.push_back(d);
        }
        sign = Sign(val[0] == '-');
        purify();
    }
    string toString() const {
        if (zero()) return "0";
        string rst;
        if (sign==negative) rst = "-";
        rst += to_string(highest());
        for (int i = 2; i <= dig.size(); i++) {
            static char buf[10];
            sprintf(buf, "%04d", highest(i));
            rst += buf;
        }
        return rst;
    }
    friend istream& operator>> (istream& is, BigInteger& x) {
        string s;
        is >> s;
        x = s;
        return is;
    }
    friend ostream& operator<< (ostream& os, const BigInteger& x) {
        os << x.toString();
        return os;
    }

    int highest(int i=1) const {
        return dig[dig.size() - i];
    }
    bool zero() const {
        return dig.empty();
    }
    BigInteger& purify() {
        if (zero()) {
            sign = positive;
            return *this;
        }
        for (int i = 0; i < dig.size()-1; i++) {
            dig[i + 1] += dig[i] / D;
            dig[i] %= D;
            if (dig[i] < 0) {
                dig[i + 1]--;
                dig[i] += D;
            }
        }
        while (highest() >= D) {
            dig.push_back(highest() / D);
            dig[dig.size() - 2] %= D;
        }
        while (!zero() && !highest()) {
            dig.pop_back();
        }
        if (zero()) {
            sign = positive;
        }
        return *this;
    }


    static DigSet add(const DigSet& x, const DigSet& y) {
        DigSet rst = x.size() > y.size() ? x : y;
        const DigSet& less = x.size() > y.size() ? y : x;
        for (int i = 0; i < less.size(); i++) {
            rst[i] += less[i];
        }
        return rst;
    }
    static DigSet sub(DigSet x, const DigSet& y) {
        for (int i = 0; i < y.size(); i++) {
            x[i] -= y[i];
        }
        return x;
    }
    static int cmp(const DigSet& x, const DigSet& y) {
        if (x.size() < y.size()) return -1;
        else if (x.size() > y.size()) return 1;
        for (int i = x.size()-1; i >= 0; i--) {
            if (x[i] < y[i]) return -1;
            else if (x[i] > y[i]) return 1;
        }
        return 0;
    }
    bool operator< (const BigInteger& b) const {
        if (sign != b.sign) return sign==negative;
        else return cmp(dig, b.dig) == (int)sign*2-1;
    }
    bool operator== (const BigInteger& b) const {
        return sign == b.sign && cmp(dig, b.dig) == 0;
    }
    bool operator<= (const BigInteger& b) const {
        return *this == b || *this < b;
    }
    BigInteger operator+ (const BigInteger& b) const {
        if (sign == b.sign) {
            return BigInteger(add(dig, b.dig), sign).purify();
        }
        else {
            return *this- -b;
        }
    }
    BigInteger operator-() const {
        return BigInteger(dig, (Sign)!sign);
    }
    BigInteger operator-(const BigInteger& b) const {
        if (sign == b.sign) {
            int c = cmp(dig, b.dig);
            if (c == 0) return BigInteger().purify();
            else if (c == 1) return BigInteger(sub(dig, b.dig), sign).purify();
            else return BigInteger(sub(b.dig, dig), (Sign)!sign).purify();
        }
        else {
            return *this+ -b;
        }
    }
    BigInteger operator*(const BigInteger& b) const {
        BigInteger rst(DigSet(dig.size() + b.dig.size()), Sign(sign!=b.sign));
        for (int i = 0; i < dig.size(); i++) {
            for (int j = 0; j < b.dig.size(); j++) {
                rst.dig[i + j] += dig[i] * b.dig[j];
                rst.dig[i + j + 1] += rst.dig[i + j] / D;
                rst.dig[i + j] %= D;
            }
        }
        return rst.purify();
    }
    BigInteger operator/ (const BigInteger& b) const {
        BigInteger rst(DigSet(dig.size()), Sign(sign != b.sign));
        BigInteger div;
        for (int i = dig.size()-1; i>=0; i--) {
            div = div * D + dig[i];
            BigInteger mul(b.dig, positive);
            for (int j = 0x2000; j; j >>= 1) {
                if (mul*j <= div) {
                    rst.dig[i] |= j;
                    div = div - mul * j;
                }
            }
        }
        return rst.purify();
    }
    BigInteger operator% (const BigInteger& b) const {
        BigInteger rst = *this - *this / b * b;
        return rst.sign == positive ? rst : b.sign == positive ? rst + b : rst - b;
    }
};

struct node
{
	BigInteger big;
	char s[1005];
	bool operator <(const node& b)const
	{
		return big<b.big;
	}
};
int n;
BigInteger sum;
node a[1005];
vector<int> vec;

int main()
{
	cin>>n>>sum;
	for(int i=0;i<n;i++)
	{
		scanf("%s",a[i].s);
		cin>>a[i].big;
	}
	sort(a,a+n);
	for(int i=n-1;i>=0;i--)
	{
		if(a[i].big<=sum)
		{
			sum=sum-a[i].big;
			vec.push_back(i);
		}
	}
	if(sum.zero())
	{
		int len=vec.size();
		printf("%d\n",len);
		for(int i=0;i<len;i++)
			printf("%s\n",a[vec[i]].s);
	}
	else
		printf("0\n");
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值