P1450 [HAOI2008] 硬币购物 dp 容斥 —— s - c[i]*(d[i]+1)怎么理解

[HAOI2008] 硬币购物 - 洛谷

看了洛谷许多题解,一开始理解不了为什么是 s - c[i]*(d[i]+1),为什么要+1呢?

其实是dp理解的不好。

这里的意思就是该枚硬币先超过限制,接下来剩下的背包也要填满,4种硬币随便组合的情况数。

------------------

首先这些题解是假设4种硬币都无限的完全背包。

(dp[ i ] ,i指的钱数,dp值是情况数。)

然后我们思考,这四种硬币是组合的,也就是第一种的所有情况上加第二种的所有情况...

也就是dp[s]已经是四种硬币的组合的情况数了。

容斥定理会吧?(其实证明我也不会,这个大学离散数学里有,但是证明比较奇怪,我没有看懂)

因为四种硬币的数量并不是无限,所以我们上面的dp要减去不合理的。

1,2,3,4可能单独不合理,也可能若干个同时不合理,所以要用容斥定理来计算。(避免重复)

即减去1,2,3,4不合理的,加上12,13,14,23,24,34两个不合理的,减去3个不合理的,加上4个不合理的。

然后就是不合理的数目的计算了,是s - (d[i] + 1) * c[ i ]

是的,我们正常只能对第i个组合到价值d[i] * c[i],但是这里是dp,接下来仍可能接着有c[i]。

所以我们计算不合理的,从不合理的开始 开始计算。

也就是我们取d[ i ]+ 1开始,在dp中接下来会取该硬币若干或者不取,所以从这里开始,这个算1种,接下来仍要填满背包,所以剩下的硬币随便组合,我们算的就是剩下硬币的组合数 ------ dp[ s - (d[i] + 1) * c[ i ] ]。

代码:

cpp 复制代码
int c[5];
int d[5];
int s;
int getw(int aim)
{
	return c[aim] * (d[aim]+1);
}

void solve()
{
	for (int i = 1; i <= 4; i++)
	{
		cin >> c[i];
	}
	int n;
	cin >> n;
	vector<int>dp(100005);
	dp[0] = 1;
	for (int i = 1; i <= 4; i++)
	{
		for (int j = c[i]; j <= 100000; j++)
		{
			dp[j] += dp[j - c[i]];
		}
	}


	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= 4; j++)
		{
			cin >> d[j];
		}
		cin >> s;
		int ans = dp[s];

		for (int i = 1; i < 16; i++)
		{
			int tmp = 0;
			int cnt = 0;//奇数减,偶数加,容斥
			if (i & 1)
			{
				tmp += getw(1); cnt++;
			}
			if (i & 2)
			{
				tmp += getw(2); cnt++;
			}
			if (i & 4)
			{
				tmp += getw(3); cnt++;
			}
			if (i & 8)
			{
				tmp += getw(4); cnt++;
			}
			if (tmp > s)continue;
			
			if (cnt % 2 == 0)
				ans += dp[s - tmp];
			else
				ans -= dp[s - tmp];
		}
		cout << ans << endl;
	}

}
signed main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}
相关推荐
神奇小永哥11 分钟前
那些年踩过的坑之Arrays.asList
java·开发语言
军训猫猫头19 分钟前
89.WPF 中实现便捷的数字输入框:DecimalUpDown 控件的使用 WPF例子 C#例子.
开发语言·c#·wpf
Light6040 分钟前
智启未来:深度解析Python Transformers库及其应用场景
开发语言·python·深度学习·自然语言处理·预训练模型·transformers库 |·|应用场景
一个天蝎座 白勺 程序猿42 分钟前
Python爬虫(5)静态页面抓取实战:requests库请求头配置与反反爬策略详解
开发语言·爬虫·python
一眼青苔1 小时前
python环境使用conda,conda如何升级默认的python版本
开发语言·python·conda
_w_z_j_1 小时前
C++----模拟实现string
开发语言·c++
张槊哲1 小时前
const(C++)
开发语言·c++
沐知全栈开发1 小时前
MongoDB 创建数据库
开发语言
ErizJ2 小时前
Golang | 迭代器模式
开发语言·golang·迭代器模式
牙痛不能吃糖,哭2 小时前
C++面试复习日记(8)2025.4.25,malloc,free和new,delete的区别
开发语言·c++