P6567

题面

题意

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

分析

由于物品数量 \(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;
}
posted @ 2020-05-27 20:01  Macesuted  阅读(139)  评论(0编辑  收藏  举报