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;
}