LG6567 [NOI Online #3 入门组]买表

发布于 2020-05-27  3.26k 次阅读


题面

题意

大致就是你有若干种货币,每种货币都有各自的价格,并且每种货币都有一定的数量。现在有若干物品,每种物品都有自己的价格,现在问你对于每一种物品的价格能否直接用已有的货币凑出。

分析

由于物品数量 $m$ 最大可达 $10^5$,对于每个物品进行方案的枚举肯定是不可行的。又看到 $n$ 非常小,并且 钞票的面值和物品的价格都在 $5\times10^5$ 以下,所以我们自然想到了预处理出 $1\to5*10^5$ 中所有的价格的可能性,然后对于每个询问 $O(1)$ 查找。

我们可以使用完全背包,我们有物品,物品的价值为货币的面值,物品的数量为货币的数量,背包的大小为每件物品的价格。

代码

int k[205], a[205], x[2005], cnt = 0;
int f[500005];

int main()
{
    int n = io.read<int>(), m = io.read<int>();
    for (int i = 0; i < n; i++)
    {
        k[i] = io.read<int>();
        a[i] = io.read<int>();
        int t = a[i];
        for (int j = 1; j <= t; j <<= 1)
        {//二进制优化
            t -= j;
            if (j * k[i] > 500000)
                break;
            x[++cnt] = j * k[i];
        }
        if (t)
            x[++cnt] = t * k[i];
    }
    f[0] = 1;//转化为0/1背包
    for (int i = 1; i <= cnt; i++)
        for (int j = 500000; j >= x[i]; j--)
            f[j] |= f[j - x[i]];
    for (int i = 0; i < m; i++)
    {//最后对于每个询问O(1)查找
        int q = io.read<int>();
        if (f[q])
            io.putchar('Y'), io.putchar('e'), io.putchar('s');
        else
            io.putchar('N'), io.putchar('o');
        io.putchar('\n');
    }
    io.finish();
    return 0;
}

我缓慢吐出一串啊吧啊吧并不再想说话