【UOJ|【UOJ #110】【APIO 2015】Bali Sculptures
【【UOJ|【UOJ #110】【APIO 2015】Bali Sculptures】http://uoj.ac/problem/110
这道题subtask4和subtask5是不同的算法。
主要思想都是从高位到低位贪心确定答案。
对于subtask4,n比较小,设\(f(i,j)\)表示前\(i\)个雕塑分成\(j\)组能否满足当前答案,最后检查\(f(n,A\sim B)\)是否有值为true的,时间复杂度\(O(n^3\log\sum Y_i)\)。
对于subtask5,n比较大,但A=1,设\(f(i)\)表示前\(i\)个雕塑要满足当前答案最少能分成多少组,最后检查\(f(n)\)是否不大于B,时间复杂度\(O(n^2\log\sum Y_i)\)。
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 2003;
int n, A, B, Y[N];
ll sum[N], num = (1ll << 41) - 1;
namespace lalala {
bool f[N][N];
bool can(ll x) {
f[0][0] = true;
for (int i = 1;
i <= n;
++i)
for (int j = 1;
j <= B && j <= i;
++j) {
f[i][j] = false;
for (int k = i - 1;
k >= 0;
--k)
if (((sum[i] - sum[k]) | x) <= x && f[k][j - 1]) {
f[i][j] = true;
break;
}
}
for (int i = A;
i <= B;
++i) if (f[n][i]) return true;
return false;
}void solve() {
for (int i = 40;
i >= 0;
--i)
if (can(num ^ (1ll << i))) num ^= (1ll << i);
printf("%lld\n", num);
}
}namespace hahaha {
int f[N];
bool can(ll x) {
for (int i = 1;
i <= n;
++i) {
f[i] = B + 1;
for (int j = i - 1;
j >= 0;
--j)
if (((sum[i] - sum[j]) | x) <= x && f[j] + 1 < f[i])
f[i] = f[j] + 1;
}
return f[n] <= B;
}void solve() {
for (int i = 40;
i >= 0;
--i)
if (can(num ^ (1ll << i))) num ^= (1ll << i);
printf("%lld\n", num);
}
}int main() {
scanf("%d%d%d", &n, &A, &B);
for (int i = 1;
i <= n;
++i) scanf("%d", Y + i), sum[i] = sum[i - 1] + Y[i];
if (A == 1) hahaha::solve();
else lalala::solve();
return 0;
}
转载于:https://www.cnblogs.com/abclzr/p/6728841.html
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长