【main idea】
Given \ (A \) , \ (B \) , so that the element is divided into a section \ (A \ le x \ le B \) group, the contribution of each element of the group and to minimize the contribution of all groups and oR operation.
【analysis】
Did not see the beginning of a dazzling range of continuous this condition,She made a false feeling of title。。。
Thinking is easy to think of a \ (dp \) formula, let \ (f [i] [j ] \) before the representation \ (i \) elements, divided into \ (j \) minimizing the answer to a group, consider enumeration transfer point \ (k \) , and then transferred. . . .
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const ll INF = 5e18;
const int MAX = 2000 + 5;
inline ll read() {
ll res = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = 1; ch = getchar(); }
while (ch <= '9' && ch >= '0') { res = (res << 3) + (res << 1) + ch - '0'; ch = getchar(); }
return f ? (~ res + 1) : res;
}
ll n, A, B, Y[MAX], sum[MAX], f[MAX][MAX], ans = INF;
int main() {
n = read(), A = read(), B = read();
for (int i = 1;i <= n; ++i)
for (int j = 0;j <= n; ++j) f[i][j] = INF;
for (int i = 1;i <= n; ++i) Y[i] = read(), sum[i] = sum[i - 1] + Y[i], f[i][1] = sum[i];
for (int i = 1;i <= n; ++i) {
int limit = min((ll)i, B);
for (int j = 2;j <= limit; ++j) {
for (int k = 1;k < i; ++k) {
f[i][j] = min(f[i][j], f[k][j - 1] | (sum[i] - sum[k]));
}
}
}
for (int i = A;i <= B; ++i) ans = min(ans, f[n][i]);
printf("%lld", ans);
return 0;
}
To submit. . what! \ (75Pt \) ? ? ? \ (TLE \) I can also accept, as well as the point \ (WA \) ?
Think carefully about it and found this formula is not satisfied with no after-effect . why? You select the previous minimize it, but in operation or under influence behind you is not known. In other words, this question, if before pressing the \ (dp \) equation metastasis, local optimal solution is not the global optimal solution.
We need to rethink.
A or the binary operation and topicsobviouslyTips, think of splitting consider binary digits, and because minimized, greedily began to consider each one from the highest level.
For each \ (POS \) , we \ (f [i] [j ] \) represented by the former \ (I \) elements divided into \ (J \) group, able to make the current bit is \ ( 0 \) (because you want to minimize thing).
Enumeration transition point \ (K \) , if the \ (f [k] [j -1] \) is true, and \ (sum [k + 1 ... i] \) in the current \ (POS \) bits is the \ (0 \) , then it can be transferred from \ (F [I] [J] =. 1 \) . Then the cumulative \ (ANS \) .
If there \ (f [n] [i ] = 1 (A \ le i \ le B) \) then this bit will be equal to \ (0 \) .
Think carefully, we will find that if do this directly, there may exist a packet of the packet with highs in the low conflict. Obviously, we should retain the case of high packet, so that we should have retained a good bit of the match before the state, and allow the transfer can not occur conflict with the state.
Then think about subtasks \ (5 \) .
We will find it has the particularity of data: \ (A = 1 \) .
How special? Packet no limit!
I recorded directly least how many groups can let \ (pos \) bits can fill \ (0 \) is not on the list?
Set \ (g [i] \) representing the forward \ (I \) bits can be divided into many groups happened that the current bit \ (POS \) can fill \ (0 \) , then the same, as long as the transition condition, there is \ (G [I] = min (G [I], G [K] +. 1) \) . Inter \ (g [0] = 0 \) , the rest \ (G \) are \ (INF \) .
Then he wrote segments \ (dp \) .
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define ll long long
#define Re register
using namespace std;
const int MAX = 2000 + 5;
inline ll read() {
ll res = 0; bool f = 0; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = 1; ch = getchar(); }
while (ch <= '9' && ch >= '0') { res = (res << 3) + (res << 1) + ch - '0'; ch = getchar(); }
return f ? (~ res + 1) : res;
}
ll Y[MAX], sum[MAX], f[MAX][MAX], ans;
int n, A, B, g[MAX];
bool flag;
inline void solution_1() {
int limit = log2(sum[n]) + 1;
for (int pos = limit; pos >= 0; --pos) {
ll res = ans | ((1LL << pos) - 1LL);
memset(g, 127, sizeof g);
g[0] = 0;
for (int i = 1;i <= n; ++i) {
for (int k = 0;k < i; ++k) {
if (((sum[i] - sum[k]) | res) == res) {
g[i] = min(g[i], g[k] + 1);
}
}
}
if (g[n] > B) ans |= (1LL << pos);
}
}
inline void solution_2() {
int limit = log2(sum[n]) + 1;
for (int pos = limit;pos >= 0; --pos) {
ll res = ans | ((1LL << pos) - 1LL);
memset(f, 0, sizeof f);
f[0][0] = 1;
flag = 0;
for (int i = 1;i <= n; ++i) {
int up = min(i, (int)B);
for (int j = 1;j <= up; ++j) {
for (int k = j - 1;k < i; ++k) {
if (f[k][j - 1] && ((sum[i] - sum[k]) | res) == res) {
f[i][j] = 1;
}
}
}
}
for (int i = A;i <= B; ++i) if (f[n][i]) flag = 1;
if (!flag) ans |= (1LL << pos);
}
}
int main() {
n = read(), A = read(), B = read();
for (int i = 1;i <= n; ++i) Y[i] = read(), sum[i] = sum[i - 1] + Y[i];
if (A == 1) solution_1();
else solution_2();
printf("%lld", ans);
return 0;
}