BZOJ1042: [HAOI2008]硬币购物

本文介绍了一种使用容斥原理解决背包问题的方法。针对有限制条件的背包问题,通过预先计算无限制情况下的解空间,再利用容斥原理排除不符合条件的情况,最终得出精确解答。文章附带了详细的C++实现代码。

 转自 http://www.cnblogs.com/zhuohan123/p/3284272.html

这个相当神奇,用容斥原理做背包。

首先,我们要先处理出四种钞票都不限的方案数。

对于每一个询问,我们利用容斥原理,答案为:得到S所有超过数量限制的方案数-硬币1超过限制的方案数-硬币2超过限制的方案数-硬币3超过限制的方案数-硬币4超过限制的方案数+硬币1、2超过限制的方案数+…+硬币1、2、3、4均超过限制的方案数。

而对于每种方案数的求法,也非常简单:假设我们要求的是F[S],则硬币1超过限制(即硬币1取的个数≥d[1]+1,不考虑硬币2、3、4是否超过限制)时的方案数即为F[S-(d[1]+1)×c[1]]。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int c[5];
long long F[110000];
struct{long long operator[](int pos){return pos<0?0:F[pos];}}f;
int main(int argc, char *argv[])
{
    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=0;j<=100000;j++)
        if(j+c[i]<=100000)F[j+c[i]]+=F[j];
    while(T--)
    {
        int d[5],s;scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
        long long ans=f[s];
        ans-=f[s-(d[1]+1)*c[1]];
        ans-=f[s-(d[2]+1)*c[2]];
        ans-=f[s-(d[3]+1)*c[3]];
        ans-=f[s-(d[4]+1)*c[4]];
        ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]];
        ans+=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]];
        ans+=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]];
        ans+=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
        ans+=f[s-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
        ans+=f[s-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
        ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
        ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
        ans-=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
        ans-=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
        ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
        #ifdef ONLINE_JUDGE
            printf("%lld\n",ans);
        #else
            printf("%I64d\n",ans);
        #endif
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值