bzoj1042: [HAOI2008]硬币购物

1042: [HAOI2008]硬币购物

Time Limit: 10 Sec  Memory Limit: 162 MB

Description

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

Input

  第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000

Output

  每次的方法数

Sample Input

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

Sample Output

4
27
题解:容斥原理,首先我们可以背包得到Smax的方案数,如果numB有限制,那么不符合的方案数就是f[Smax - (numB + 1) Vb], 然后容斥一波, 容斥用搜索比较好,奇加偶减;
#include <bits/stdc++.h>
 
using namespace std;
const int M = 100005;
int a[5], b[5];
long long ans, f[M];
 
void dfs(int dep, int x, int sum){
    if(sum < 0)return;
    if(x == 5){
        if(dep & 1) ans += f[sum];
        else ans -= f[sum];
        return ;
    }
 
    dfs(dep+1, x+1, sum - (b[x] + 1) * a[x]);
    dfs(dep, x+1, sum);
}
int main()
{
    f[0] = 1;
    int tot;
    scanf("%d%d%d%d%d",&a[1], &a[2], &a[3], &a[4], &tot);
    for(int j = 1; j <= 4; j++)
        for(int i = 1; i <= M; i++)
            if(i - a[j] >= 0) f[i] += f[i - a[j]];
    //for(int i = 1; i <= 1005; i++)printf("%I64d ", f[i]);
    while(tot--){
        int s;
        scanf("%d%d%d%d%d", &b[1], &b[2], &b[3], &b[4], &s);
        ans = 0;
        dfs(1, 1, s);
        printf("%lld\n", ans);
    }
}
View Code

 

posted @ 2018-07-18 15:59  Ed_Sheeran  阅读(...)  评论(... 编辑 收藏