bzoj 1042: [HAOI2008]硬币购物

Posted lxy8584099

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1042: [HAOI2008]硬币购物相关的知识,希望对你有一定的参考价值。

神奇的容斥 什么都能干

 

/**************************************************************
    Problem: 1042
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:44 ms
    Memory:1604 kb
****************************************************************/
 
/*
    容斥
    先算出每个都不限制的背包
    然后对于一个di限制 其他都不限制 个数就是 f[s-ci*(di+1)] 
    对于容斥 奇减偶加 
*/
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+50;
int c[5],tot;
ll f[N];
int d[5],s;
int F(int x)
{
    return c[x]*(d[x]+1);
}
int main()
{
    scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&tot);
    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(tot--)
    {
        scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
        ll ans=f[s];
        if(s-F(1)>=0) ans-=f[s-F(1)];
        if(s-F(2)>=0) ans-=f[s-F(2)];
        if(s-F(3)>=0) ans-=f[s-F(3)];
        if(s-F(4)>=0) ans-=f[s-F(4)];
        if(s-F(1)-F(2)>=0) ans+=f[s-F(1)-F(2)];
        if(s-F(1)-F(3)>=0) ans+=f[s-F(1)-F(3)];
        if(s-F(1)-F(4)>=0) ans+=f[s-F(1)-F(4)];
        if(s-F(3)-F(2)>=0) ans+=f[s-F(3)-F(2)];
        if(s-F(4)-F(2)>=0) ans+=f[s-F(4)-F(2)];
        if(s-F(3)-F(4)>=0) ans+=f[s-F(3)-F(4)];
        if(s-F(1)-F(2)-F(3)>=0) ans-=f[s-F(1)-F(2)-F(3)];
        if(s-F(1)-F(2)-F(4)>=0) ans-=f[s-F(1)-F(2)-F(4)];
        if(s-F(4)-F(2)-F(3)>=0) ans-=f[s-F(4)-F(2)-F(3)];
        if(s-F(1)-F(3)-F(4)>=0) ans-=f[s-F(1)-F(3)-F(4)];
        if(s-F(1)-F(2)-F(3)-F(4)>=0) ans+=f[s-F(1)-F(2)-F(3)-F(4)];
        printf("%lld
",ans);
    }
     
     
    return 0;
}

 

以上是关于bzoj 1042: [HAOI2008]硬币购物的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1042[HAOI2008]硬币购物 容斥

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

bzoj 1042: [HAOI2008]硬币购物

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

bzoj1042 HAOI2008—硬币购物

[bzoj1042] [HAOI2008]硬币购物