Luogu P1450 [HAOI2008]硬币购物

Posted hawking-llfz

tags:

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


Luogu P1450 [HAOI2008]硬币购物

解析

  • 刚开始以为是道多重背包题,但看到数据范围后发现此题并不简单
  • 首先用完全背包预处理出硬币数量不限制时需要钱的数量 $ \leq 100000 $ 的所有情况
  • 发现在预处理中会有不合法的情况,也就是超过硬币数量限制的情况,需要减去
  • 容斥原理,减去一枚硬币不合法的情况,加回两枚硬币不合法的情况,减去三枚硬币不合法的情况,加回四枚硬币不合法的情况,这里的处理就是通过 $ \pm f[s - c_i * (d_i + 1)] $ 得到,可以通过枚举子集实现

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int tot,s,t,c[5],d[5];
LL ans,f[100005];
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]];
    t=(1<<4)-1;
    while(tot--)
    
        scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
        ans=f[s];
        for(int i=t;i;i=(i-1)&t)
        
            LL res=0;
            bool frog=0;
            for(int j=1;j<=4;j++)
            
                if(i&(1<<(j-1)))
                
                    frog^=1;
                    res+=c[j]*(d[j]+1);
                
            
            if(s>=res)
            
                if(frog) ans-=f[s-res];
                else ans+=f[s-res];
            
        
        printf("%lld\n",ans);
    
    return 0;

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

容斥定理背包问题P1450 [HAOI2008]硬币购物

容斥定理背包问题P1450 [HAOI2008]硬币购物

容斥定理背包问题P1450 [HAOI2008]硬币购物

P1450 [HAOI2008]硬币购物

P1450 [HAOI2008]硬币购物

题解 P1450 [HAOI2008]硬币购物