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]硬币购物的主要内容,如果未能解决你的问题,请参考以下文章