P1450 [HAOI2008] 硬币购物 题解

原题链接:P1450

这道题被教练放到了状压 \(DP\) 的题单里面,但是正解却不是状压 \(DP\),而是背包 \(+\) 神奇容斥,只不过是用到了一些二进制状压的思想。

思路

首先看到题目立马就想到了多重背包,但是时间复杂度肯定接受不了,于是考虑优化背包。我们可以想到一个很神奇的性质:假设只有一种硬币,看到限制条件每种硬币只能用 \(d\) 个,发现其实方案数就等于每个硬币可以用无限次的方案数减去硬币用了 \(d\) 次以上的方案数。通过这个性质,我们考虑可以用容斥来做这道题。先用完全背包求出每个硬币都可以用无限次的方案数,再用容斥计算出最终的答案。

  • 设计状态

显然,设 \(dp_{i}\) 表示每个硬币都可以用无限次,拼出 \(i\) 的方案数。

  • 方程转移

和完全背包类似:\(dp_{j}=dp_{j}+dp_{j-c_{i}}\)

  • 容斥

这是本道题最重要的一部分了。

我们已经算出了每个硬币都可以用无限次,拼出 \(s\) 的方案数 \(dp_{s}\) 了,只需要减掉每种硬币用了超过 \(d\) 个的情况。可以把第 \(i\) 种硬币强制支付 \(d+1\) 个,这样就一定是不合法(需要减掉)的。那么强制支付 \(d+1\) 个后的方案数是多少呢?其实就是 \(dp_{s-(d+1)\times c_{i}}\)。这个转化十分巧妙。但是如果减掉了这四种情况还是错的,因为多减了两个及以上都超过 \(d\) 个的情况。于是用容斥原理算一遍就可以了。

容斥原理:card(A∪B)=card(A)+card(B)−card(A∩B)

多个元素的容斥可以递推了,可以发现一些性质:奇数加,偶数减。这样我们可以用一个四位的二进制数来表示,第 \(i\) 位为 \(1\) 就表示第 \(i\) 个硬币超过了题目的条件。然后通过 \(1\) 的个数来判断是加还是减,再用 \(sum\) 来记录 \(\sum (d+1)\times c_{i}\) 就可以了。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f
#define inf_db 1x27
#define ls id << 1 
#define rs id << 1 | 1
#define re register
typedef pair <int,int> pii;
const int MAXN = 1e5 + 10;
const int MAXM = 10;
int c[MAXM],d[MAXM],n,s,dp[MAXN];
signed main()
{
	for(int i = 1;i <= 4;i++) cin >> c[i];
	cin >> n;
	dp[0] = 1;
	for(int i = 1;i <= 4;i++)
	    for(int j = c[i];j <= 1e5;j++) dp[j] += dp[j - c[i]];
	while(n--)
	{
		for(int i = 1;i <= 4;i++) cin >> d[i];
		cin >> s;
		int ans = dp[s];
		for(int i = 1;i <= 15;i++)
		{
			int k = 0,num = 0,fl;
			for(int j = 1;j <= 4;j++)
			{
				if(!(i & (1 << j - 1))) continue;
				num++;
				k += c[j] * (d[j] + 1);
			}
			if(num % 2 == 0) fl = 1;
			if(num % 2 == 1) fl = -1;
			if(s >= k) ans += dp[s - k] * fl; 
		}
		cout << ans << endl;
	}
	return 0;
}
posted @ 2023-12-19 11:49  Creeper_l  阅读(60)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
  3. 3 True love tired
  4. 4 一笑江湖 (DJ弹鼓版) 闻人听書_
  5. 5 最好的安排 曲婉婷
  6. 6 星星在唱歌 司南
  7. 7 山川 李荣浩
  8. 8 On My Way Alan Walker
  9. 9 百战成诗 王者荣耀·100英雄官方群像献礼歌
  10. 10 雪 Distance Capper / 罗言
  11. 11 Edamame bbno$ / Rich Brian
  12. 12 半生雪 七叔-叶泽浩
  13. 13 Catch My Breath Kelly Clarkson
  14. 14 Love Is Gone SLANDER / Dylan Matthew
  15. 15 Endless Summer Alan Walker / Zak Abel
  16. 16 悬溺 葛东琪
  17. 17 风吹丹顶鹤 葛东琪
  18. 18 Normal No More TYSM
  19. 19 哪里都是你 队长
  20. 20 Stronger Kelly Clarkson
  21. 21 廖俊涛
  22. 22 消愁 毛不易
  23. 23 The Runner Yubik
  24. 24 踏山河 七叔-叶泽浩
  25. 25 Waiting For Love Avicii
  26. 26 在你的身边 盛哲
  27. 27 Dream It Possible Delacey
  28. 28 凄美地 郭顶
  29. 29 满天星辰不及你 ycc
  30. 30 侧脸 于果
  31. 31 阿拉斯加海湾 蓝心羽
  32. 32 虞兮叹 闻人听書_
  33. 33 离别开出花 就是南方凯
  34. 34 盗墓笔记·十年人间 李常超 (Lao乾妈)
イエスタデイ(翻自 Official髭男dism) - 茶泡饭,春茶,kobasolo
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.