[BZOJ] 1042: [HAOI2008]硬币购物

 

每种硬币用完全背包算出,直接容斥

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define P(i) (c[i] * (d[i] + 1))

using namespace std;

const int MAXN=100005;

int c[5],d[5],s;
int cnt;
long long f[MAXN],ans;

int main(){
    for(int i = 1; i <= 4; i++) cin>>c[i];
    cin >> cnt;
    for(int i = 1; i <= cnt; i++) {
        for(int j = 1; j <= 4; j++) cin>>d[j];
        cin>>s;
        memset(f,0,sizeof(f));
        f[0] = 1;
        for(int k = 1; k <= 4; ++k)
            for(int j = c[k]; j <= s; j++)
                f[j] += f[j - c[k]];
        ans = f[s];
        for(int k = 1; k <= 4; ++k)
            if(s - P(k) >= 0)
                ans -= f[s - P(k)];
        if(s - P(1) - P(2) >= 0) ans += f[s - P(1) - P(2)];
        if(s - P(2) - P(3) >= 0) ans += f[s - P(2) - P(3)];
        if(s - P(3) - P(4) >= 0) ans += f[s - P(3) - P(4)];
        if(s - P(2) - P(4) >= 0) ans += f[s - P(2) - P(4)];
        if(s - P(1) - P(3) >= 0) ans += f[s - P(1) - P(3)];
        if(s - P(1) - P(4) >= 0) ans += f[s - P(1) - P(4)];
        if(s - P(1) - P(2) - P(3) >= 0)  ans -= f[s - P(1) - P(2) - P(3)];
        if(s - P(2) - P(3) - P(4) >= 0)  ans -= f[s - P(2) - P(3) - P(4)];
        if(s - P(1) - P(3) - P(4) >= 0)  ans -= f[s - P(1) - P(3) - P(4)];
        if(s - P(1) - P(2) - P(4) >= 0)  ans -= f[s - P(1) - P(2) - P(4)];
        if(s - P(1) - P(2) - P(3) - P(4) >= 0)   ans += f[s - P(1) - P(2) - P(3) - P(4)];
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2018-07-28 23:55  GhostCai  阅读(94)  评论(0编辑  收藏  举报