luogu P1450 [HAOI2008]硬币购物

应该算是我做的正儿八经的容斥的第一道题吧。

直接做时间复杂度是(O(4nS))的,显然不能接受。注意到这题只有(4)个物品,考虑容斥。

容斥模型

  • 元素:每一种方案
  • 全集:所有组合总和为(n)的方案
  • 属性:对每个物品购买的数量限制

这道题显然是对每个属性求交集,于是转化成了全集-补集的并集模型,由于只有(4)个物品,所以可以直接预处理+暴力枚举,时间复杂度(O(4max(S),2^4n))

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long LL;
const int N=100000;
int c[5],n,d[5],s;
LL f[N+9];

void init()
{
	for (int i=1;i<=4;i++)
		scanf("%d",&c[i]);
	scanf("%d",&n);
	f[0]=1;
	for (int i=1;i<=4;i++)
		for (int j=c[i];j<=N;j++)
			f[j]+=f[j-c[i]];
}

void work()
{
	while(n--)
	{
		for (int i=1;i<=4;i++)
			scanf("%d",&d[i]);
		scanf("%d",&s);
		LL ans=0;
		for (int i=1;i<16;i++)
		{
			int cnt=0;LL m=s;
			for (int j=1;j<=4;j++)
				if(i&(1<<j-1))
					cnt++,m-=1ll*(d[j]+1)*c[j];
			if(m>=0) ans+=(cnt&1)?f[m]:-f[m];
		}
		printf("%lld
",f[s]-ans);
	}
}

int main()
{
	init();
	work();
	return 0;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
原文地址:https://www.cnblogs.com/With-penguin/p/13053294.html