ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[HAOI2008]硬币购物

2022-05-16 22:32:20  阅读:176  来源: 互联网

标签:超量 硬币 int 购物 wh ans HAOI2008 getchar


link

一开始以为是一道智商税题目,结果发现似乎并没有那么简单。这道题给我提供了许多很有价值的思路。

首先多重背包是肯定会死的,二进制拆分似乎也并不是很有用处 (\(O(QN\log N)\)肯定超时),于是想到整体减空白。

整体是什么?显然会是没有限制,也就是所有硬币随便用时的方案数,此时直接暴力完全背包预处理即可。那空白呢?

空白的意义可以认为是强制硬币使用超量的情况。既然强制硬币超量,那么大可以先把超量硬币的面额减去,那么剩下的钱不管怎么花最后整体结果都是不合法的,而后者的计算就转换到了整体部分了,于是解决问题就只差个容斥了。可以枚举1到16,然后1的个数判加减即可,基本容斥。

#include<cstdio>
#define zczc
#define int long long
const int N=100010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,now,ans,num,s[N],a[5],b[5];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	s[0]=1;
	for(int i=1;i<=4;i++){
		read(a[i]);
		for(int j=a[i];j<N;j++)s[j]+=s[j-a[i]];
	}
	read(m);
	while(m--){
		for(int i=1;i<=4;i++)read(b[i]);
		ans=0;read(n);
		for(int i=0;i<16;i++){
			now=n,num=0;
			for(int j=1;j<=4;j++){
				if(i&(1<<j-1)){
					now-=a[j]*(b[j]+1);
					num++;
				}
			}
			if(now>=0)ans+=((num&1)?-1:1)*s[now];
		}
		printf("%lld\n",ans);
	}
	
	return 0;
}

标签:超量,硬币,int,购物,wh,ans,HAOI2008,getchar
来源: https://www.cnblogs.com/dai-se-can-tian/p/16278865.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有