CF1854B Earn or Unlock 题解
本题有一个重要的性质:设最终包括
感性理解:如果将一张权值为
所以,我们只用判断是否存在一种方案使得恰好解锁
设 bool 类型的
直接这样写会 TLE,考虑将 dp 数组定义为一个 bitset,用 bitset 加速转移:
dp = (dp | (dp << a[i]));
注意,做完这句语句后,要将
最后枚举解锁的卡片的数量 ans 取最大值。
注意, dp 数组要开到
原因是,有可能可以解锁的卡片数量超过了
2
2 114514
正确的输出应为 114514,是因为
下面给出代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 200000;
const ll N = maxn + 10;
ll n, m, ans, a[N], s[N];
bool f[N];
bitset<N> dp;
int main() {
scanf("%lld", &n);
s[0] = 0;
for (ll i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
s[i] = s[i - 1] + a[i];
}
dp[1] = 1;
for (ll i = 1; i <= n; ++i) {
dp = (dp | (dp << a[i]));
f[i] = dp[i];
dp[i] = 0;
}
for (ll i = n + 1; i <= 2 * n; ++i) {
f[i] = dp[i];
s[i] = s[i - 1];
}
ans = 0;
for (ll i = 1; i <= 2 * n; ++i) {
if (f[i]) {
ans = max(ans, s[i] - i + 1);
}
}
printf("%lld", ans);
return 0;
}
蒟蒻讲的有些地方可能有点啰嗦或者不清楚,还请巨佬们谅解!