[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]硬币购物的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1042: [HAOI2008]硬币购物

BZOJ1042[HAOI2008]硬币购物 容斥

bzoj 1042: [HAOI2008]硬币购物 dp+容斥原理

P1450 [HAOI2008]硬币购物

Luogu P1450 [HAOI2008]硬币购物

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