[HAOI2008] 硬币购物
[HAOI2008] 硬币购物
题目描述
共有
某人去商店买东西,去了
输入格式
输入的第一行是五个整数,分别代表
接下来
输出格式
对于每次购买,输出一行一个整数代表答案。
样例 #1
样例输入 #1
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
样例输出 #1
4
27
提示
数据规模与约定
- 对于
的数据,保证 , 。
[HAOI2008] 硬币购物
分析
第一眼看到题目,许多硬币组成一个价值的方案,限制个数,指定花费,这不就是多重背包求方案数吗?
然后注意到多次询问,每次都要做多重背包,就算是单调队列优化,复杂度也是
先分别考虑每种硬币,有限制不好搞,可以考虑用全部状态减去非法状态。
设
非法状态就是硬币至少用了
也就是说合法方案
同理,四种硬币也是总状态减去非法状态,不过四种硬币的非法情况的方案数会有重叠,这就要用容斥原理了。
设第
则
最后用
总之一句话
可以用壮压的方法枚举子集来进行容斥计算
code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=10;
int n,s;
int c[M],d[M];
ll f[N],ans;
int main ()
{
for(int i=1;i<=4;i++) cin>>c[i];
f[0]=1;
for(int i=1;i<=4;i++)
for(int j=c[i];j<N;j++)
f[j]=f[j]+f[j-c[i]];
cin>>n;
for(int i=1;i<=n;i++)
{
for(int i=1;i<=4;i++) cin>>d[i];
cin>>s;
ans=0;
for(int i=0;i<(1<<4);i++)
{
int cnt=0;
ll t=0;
for(int j=1;j<=4;j++) if(i&(1<<(j-1))) cnt++,t+=c[j]*(d[j]+1);
if(s>=t)
{
if(cnt&1) ans-=f[s-t];
else ans+=f[s-t];
}
}
cout<<ans<<"\n";
}
return 0;
}
部分语言参考:https://www.cnblogs.com/LLTYYC/p/10773808.html
https://www.luogu.com.cn/article/ywr15b0z
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」