P1450 [HAOI2008] 硬币购物

P1450 [HAOI2008] 硬币购物

已经八百年没写过题解了。

先是因为懒,后是没有时间写了。

但是这题印象属实深刻。任务列表里吃灰两个月

想到了完全背包然后容斥 bulabula 的

但是就是不知道该怎么下手。

好像也没那么复杂。

先预处理出购买价值 i 的东西的方案数,先不管限不限制个数。

然后把不合法的部分减去。

这个可以预处理出来,直接完全背包就行了。

那么什么是不合法的部分?

即要排除 >di 的情况,也就是 di+1 的情况,这部分的价值是 s(di+1)×ci,之前处理出了价值 i 的方案数,那这个是直接可以搞的, 然后容斥的加减即可。

具体的容斥证明可以看 https://www.luogu.com.cn/discuss/481921

以及不是多么困难的码。

// Problem: P1450 [HAOI2008] 硬币购物
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1450
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Author: Gym_nastics
// 
// Powered by CP Editor (https://cpeditor.org)

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define INF 0x3f3f3f3f
#define best cout<<"whw is a hreo\n";
#define int long long

const int mod=1e9+7;
const int maxn=1e6+7,maxm=2e3+1;

using namespace std;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*f;
}

int f[maxn+1],c[5],d[5],n; 
#define cl(x) (d[x]+1)*c[x]

signed main() {
	for(int i=0;i<4;i++) c[i]=read();
	f[0]=1;
	for(int i=0;i<4;i++)
	for(int j=c[i];j<=maxn-5;j++) f[j]+=f[j-c[i]];
	n=read();
	for(int i=1;i<=n;i++){
		for(int j=0;j<4;j++) d[j]=read();int s=read();
		int res=f[s];
		for(int j=1;j<16;j++){
			int k=0,sum=s;
			for(int l=0;l<4;l++) if(j&(1<<l)) k^=1,sum-=cl(l);
			if(sum>=0) res+=k?-f[sum]:f[sum];
		}
		printf("%lld\n",res);
	}
	return 0;
}

本文作者:Gym_nastics

本文链接:https://www.cnblogs.com/BlackDan/p/16647210.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Gym_nastics  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起