(最优子序列) 取m= 16,给出长度为n的整数序列$(0 \leq a_i < 2^m)$。对于一个二进制数x,定义其分值w(x)为x + popcnt(x),其中popcnt(x)表示x二进制表示中1的个数。对于一个子序列$b_1,b_2,\ldots,b_k$,定义其子序列分值S为$w(b_1 \oplus b2) + w(b2 \oplus b3) + w(b3 \oplus b4) +...+ w(b_{k-1} \oplus b_k)$。其中$\oplus$表示按位异或。对于空子序列,规定其子序列分值为0。求一个子序列使得其子序列分值最大,输出这个最大值。
输入第一行包含一个整数 $n(1 ≤n≤40000)$。接下来一行包含n个整数$a_1,a_2,\ldots,a_n$。
提示:考虑优化朴素的动态规划算法,将前$\frac{m}{2}$位和后$\frac{m}{2}$位分开计算。
Max[x][y]表示当前的子序列下一个位置的高8位是x、最后一个位置的低8位是y时的最大价值。
试补全程序。
#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 = 100000000000000LL ;
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;
}
选择题
1) ①处应填()
2) ②处应填()
3) ③处应填()
4) ④处应填()
5) ⑤处应填()