The meaning of problems
Given \ (n-\) integers \ (a_i \) and an integer \ (m \) . Locate the \ (n-\) non-negative integer, satisfying \ (b_0 <b_1 <b_2 < \ dots <b_ n \) and \ (\ sum \ text {popcount } (b_i) \ times a_i \) is the maximum value
\ (1 \ le n \ le 200 , n-1 \ le m \ le 10 ^ {18} \)
Thinking
If \ (m \) is relatively small, this question is obviously interval \ (\ DP {text} \) , \ (A [L, R & lt] \) corresponding to \ ([L, R] \ ) node. But now \ (m \) is particularly large, because to be useful bits, we can think of using \ (\ text {trie} \ ) tree. Konjac first reaction: to build it out? But we found that if each \ (\ text {trie} \ ) below nodes are full, they are all the same. I.e. we \ (m \ cdot \ text { log} m \) nodes, the nodes fall into two types, a second dimension \ (m * m \) of the reduced complexity of the \ (2 \) .
If the merger up from under, as long as we focus on whether this point is full of points, as well as the current contribution of this next layer, \ ([L, k] \) return to the left not contribute to his son, the son who owned the right to add \ (a [k + 1, r ] \) and.
- For a full point, two sons are also full points.
- For the last point on a node to the root path, you may not have the right son, then left his son a non-full points (not to say the following dissatisfaction, because it is difficult to consider, we just put the last of the points where the dragged out a special class treatment), can only put all the right son; there may have full and non-full left his son the right node, right node contributions doubled \ (a [k + 1, r] \) . Interval dp
In vain from konjac zjy to see a lot of people do not have the patience to see a man I might, if you really want to study you can go zsy chiefs there to see
#include <bits/stdc++.h>
const int N=305;
using std::max;
typedef long long ll;
int n;
ll m,a[N],f[2][2][N][N];
int main(){
scanf("%d%lld",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
for (int i=1;i<=n;i++) a[i]+=a[i-1];
int now=0;
memset(f[now],-63,sizeof(f[now]));
for (int i=1;i<=n;i++) f[now][0][i][i]=f[now][1][i][i]=0;
for (int w=1;1ll<<(w-1)<=m;w++){
now=now^1;
memset(f[now],-63,sizeof(f[now]));
for (int len=1;len<=n;len++)
for(int l=1,r=len;r<=n;l++,r++){
f[now][0][l][r]=f[now^1][0][l][r]+max(0ll,a[r]-a[l-1]);
for (int k=l;k<r;k++)
f[now][0][l][r]=max(f[now][0][l][r],f[now^1][0][l][k]+f[now^1][0][k+1][r]+a[r]-a[k]);
if ((m>>(w-1))&1){
f[now][1][l][r]=max(f[now^1][0][l][r],f[now^1][1][l][r]+a[r]-a[l-1]);
for (int k=l;k<r;k++)
f[now][1][l][r]=max(f[now][1][l][r],f[now^1][0][l][k]+f[now^1][1][k+1][r]+a[r]-a[k]);
}else f[now][1][l][r]=f[now^1][1][l][r];
}
}
printf("%lld\n",f[now][1][1][n]);
}
postscript
Large make up blog site (up finish up)