BZOJ 1042: [HAOI2008]硬币购物( 背包dp + 容斥原理 )

时间:2021-03-02 22:13:56

BZOJ 1042: [HAOI2008]硬币购物( 背包dp + 容斥原理 )

先按完全背包做一次dp, dp(x)表示x元的东西有多少种方案, 然后再容斥一下.

------------------------------------------------------------------------

#include<cstdio>
#include<algorithm>
#include<cstring>
 
using namespace std;
 
typedef long long ll;
 
const int maxn = 100009;
 
ll dp[maxn], ans;
int c[4], d[4], s;
 
void dfs(int x, int w, bool t) {
if(x == 4)
t ? ans -= dp[w] : ans += dp[w];
else {
dfs(x + 1, w, t);
if(w >= ll(c[x]) * (d[x] + 1)) dfs(x + 1, w - c[x] * (d[x] + 1), t ^ 1);
}
}
 
int main() {
for(int i = 0; i < 4; i++) scanf("%d", c + i);
memset(dp, 0, sizeof dp); dp[0] = 1;
for(int i = 0; i < 4; i++)
for(int j = c[i]; j < maxn; j++)
dp[j] += dp[j - c[i]];
int T; scanf("%d", &T);
while(T--) {
for(int i = 0; i < 4; i++) scanf("%d", d + i);
scanf("%d", &s);
ans = 0;
dfs(0, s, 0);
printf("%lld\n", ans);
}
return 0;
}

------------------------------------------------------------------------

1042: [HAOI2008]硬币购物

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1524  Solved: 892
[Submit][Status][Discuss]

Description

硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。

Input

第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s

Output

每次的方法数

Sample Input

1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900

Sample Output

4
27

HINT

数据规模

di,s<=100000

tot<=1000

Source