[HAOI2008]硬币购物
Posted zzy2005
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2008]硬币购物相关的知识,希望对你有一定的参考价值。
题解
十分精妙的一道题。
假如没有限制,就是一道简单的dp
当有了限制,很明显会有一些方案不可行。
那么,我们就可以想如何去掉不可行的。
我们可以强制让一些种类超过限定,即让c[i]取(d[i]+1)个
那么容斥一下就可以了
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
inline int gi() {
RG int x = 0; RG char c = getchar(); bool f = 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') c = getchar(), f = 1;
while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
return f ? -x : x;
}
int c[5], d[5];
LL f[100010], ans;
void dfs(int x, int k, int s) {
if (s < 0) return ;
if (x > 4) {
if (k&1) ans -= f[s];
else ans += f[s];
return ;
}
dfs(x+1, k+1, s-(d[x]+1)*c[x]);
dfs(x+1, k, s);
return ;
}
int main() {
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
for (int i = 1; i <= 4; i++) c[i] = gi();
int T = gi();
f[0] = 1;
for (int i = 1; i <= 4; i++)
for (int j = c[i]; j <= 100000; j++)
f[j] += f[j-c[i]];
while (T--) {
for (int i = 1; i <= 4; i++)
d[i] = gi();
ans = 0;
int s = gi();
dfs(1, 0, s);
printf("%lld
", ans);
}
return 0;
}
以上是关于[HAOI2008]硬币购物的主要内容,如果未能解决你的问题,请参考以下文章