六、完善程序-2

(最优子序列)取 m=16,给出长度为 n 的整数序列 a1,a2,…,an(0≤ai<2m)。对于一个二进制数 x,定义其分值 w(x)为 x+popcnt⁡(x),其中 popcnt⁡(x) 表示 x 二进制表示中 1 的个数。对于一个子序列 b1,b2,…,bk​,定义其子序列分值 S为 w(b1⊕b2)+w(b2⊕b3)+w(b3⊕b4)+⋯+w(bk−1⊕bk)。其中 ⊕ 表示按位异或。对于空子序列,规定其子序列分值为 0 求一个子序列使得其子序列分值最大,输出这个最大值。

输入第一行包含一个整数 n(1≤n≤40000)n接下来一行包含 n个整数 a1,a2,⋯,an

提示:考虑优化朴素的动态规划算法,将前 \(\frac{m}{2}\)​ 位和后 \(\frac{m}{2}\)位分开计算。

Max[x][y] 表示当前的子序列下一个位置的高 8 位是 x、最后一个位置的低 8 位是 y 时的最大价值。

试补全程序。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>

using namespace std;

typedef long long LL;

const int MAXN = 40000, M = 16, B = M >> 1, MS = (1 << B) - 1;
const LL INF = 1000000000000000LL;
LL Max[MS + 4][MS + 4];

int w(int x) 
{
    int s = x;
    while(x) 
    {
        ;
        s++;
    }
    return s;
}

void to_max(LL &x, LL y) 
{
    if(x < y)
        x = y;
}

int main() 
{
    int n;
    LL ans = 0;
    cin >> n;
    for(int x = 0; x <= MS; x++)
        for(int y = 0; y <= MS; y++)
            Max[x][y] = -INF;
    for(int i = 1; i <= n ; i++) 
    {
        LL a;
        cin >> a;
        int x =  , y = a & MS;
        LL v = ;
        for(int z = 0; z < = MS; z++)
            to_max(v, );
        for(int z = 0; z < = MS; z++)
            ;
        to_max(ans , v);
    }
    cout << ans << endl;
    return 0;
}
Scroll to Top