[HAOI2008]硬币购物

题解

十分精妙的一道题。

假如没有限制,就是一道简单的dp

当有了限制,很明显会有一些方案不可行。
那么,我们就可以想如何去掉不可行的。

我们可以强制让一些种类超过限定,即让c[i]取(d[i]+1)个

那么容斥一下就可以了

Code

#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\n", ans);
	}
	return 0;
}

posted @ 2018-12-15 14:42  zzy2005  阅读(107)  评论(0编辑  收藏  举报