[BZOJ1042][HAOI2008]硬币购物:背包DP+容斥原理

分析:

先跑一个完全背包。
然后对于每个询问,枚举是哪(些)种硬币不合法,容斥一下,减去不合法的方案数即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
typedef long long LL;

int c[5],d[5],tmp[5],s;
LL f[100005];

int main(){
    int T;
    scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&T);
    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--){
        scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
        for(int i=1;i<=4;i++) tmp[i]=c[i]*(d[i]+1);
        LL ans=0;
        for(int i=0;i<16;i++){
            int r=1;LL res=0;
            for(int j=0;j<4;j++) if((i>>j)&1) res+=tmp[j+1],r=-r;
            if(res>s) continue;
            ans+=r*f[s-res];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9749129.html