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;
}
相关推荐
一点媛艺15 分钟前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风19 分钟前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生1 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功1 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
闲晨1 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程2 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue3 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man3 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang