每日一题33. 简单瞎搞题 (滚动数组 + bitset 优化DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一题33. 简单瞎搞题 (滚动数组 + bitset 优化DP)相关的知识,希望对你有一定的参考价值。

补题链接:Here

这个问题的难点在于如何统计出所有和可能出现的情况,并且不能重复。
很容易想到用桶去存储每一个数,即某个和能够组合出来则为1,否则为0

不妨令 \\(dp[i][j]\\) 表示为第 \\(i\\) 次选择时,和为 \\(j\\) 的情况是否出现过

但是内存方面需要 \\(1e8\\)\\(int\\) 内存,显然是不可接受的

那么我们考虑用 \\(bitset\\) 优化内存,由递推方程:\\(dp_i = dp_{i}|=(dp_{i-1}<<(j*j))\\)

代表第 \\(i\\) 次选择的时候是否能从当前状态转移到和为\\(j\\) 的状态

const int N = 110;
bitset<1000010>dp[N];
void solve() {
	int n; cin >> n;
	dp[0] = 1;
	for (int i = 1, l, r; i <= n; ++i) {
		cin >> l >> r;
		for (int j = l; j <= r; ++j)dp[i] |= (dp[i - 1] << (j * j));
	}
	cout << dp[n].count() << "\\n";
}

写完状态转移方程发现 \\(dp_i\\) 仅与 \\(dp_{i - 1}\\) 有关系,所以由滚动数组来节省空间

bitset<1000010> now, nxt;
void solve() {
	int n; cin >> n;
	now[0] = 1;
	for (int i = 1, l, r; i <= n; ++i) {
		cin >> l >> r;
		for (int j = l; j <= r; ++j)
			if (j == l)nxt = (now << (j * j));
			else nxt |= (now << (j * j));
		now = nxt;
	}
	cout << now.count() << "\\n";
}

以上是关于每日一题33. 简单瞎搞题 (滚动数组 + bitset 优化DP)的主要内容,如果未能解决你的问题,请参考以下文章

力扣每日一题——NO.33——搜索旋转排序数组

每日一题找到有序数组中大于等于一个数最左的位置

每日一题找到有序数组中大于等于一个数最左的位置

2021夏季每日一题 week6 完结

[ 9.22 ]CF每日一题系列—— 484A Bits

2021暑假每日一题 week6 完结