[Solution] ● Jane Bali sculpture

【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;
}

Guess you like

Origin www.cnblogs.com/silentEAG/p/11479667.html