如果(m)是(2^w-1)的形式,那么我们可以搞一个非常厉害的区间dp,设(dp_{w,l,r})表示当(m=2^w-1)时,([l,r])的最大贡献是多少,我们枚举(i),让([l,i])的最高位填(0),([i+1,r])的最高位填(1),在这里直接算一下贡献,到下一层计算即可
处理出上面那个东西之后,按照数位dp的方式来对着m卡位就好了
代码
#include<bits/stdc++.h>
#define re register
#define LL long long
int n;LL m,a[205],pre[205];
LL dp[65][205][205],g[65][205][205];
int u[65][205][205],vis[65][205][205];
const LL inf=-1e17;
LL Dfs(int dep,int l,int r) {
if(l>r) return 0;if(!dep) return l==r?0:inf;
if(r-l+1>(1ll<<dep)) return inf;
if(vis[dep][l][r]) return dp[dep][l][r];
vis[dep][l][r]=1;LL nw=inf;
for(re int i=l-1;i<=r;++i) {
LL x=Dfs(dep-1,l,i)+Dfs(dep-1,i+1,r)+pre[r]-pre[i];
if(x>nw) nw=x;
}
return dp[dep][l][r]=nw;
}
LL Getans(int dep,int l,int r) {
if(l>r) return 0;if(!dep) return l==r?0:inf;
if(u[dep][l][r]) return g[dep][l][r];
LL nw=inf;u[dep][l][r]=1;
if(m>>(dep-1)&1) {
for(re int i=l-1;i<=r;++i) {
LL x=Dfs(dep-1,l,i)+Getans(dep-1,i+1,r)+pre[r]-pre[i];
if(x>nw) nw=x;
}
return g[dep][l][r]=nw;
}
return g[dep][l][r]=Getans(dep-1,l,r);
}
int main() {
scanf("%d%lld",&n,&m);
for(re int i=1;i<=n;i++)scanf("%lld",&a[i]),pre[i]=pre[i-1]+a[i];
LL S=m;int dep=0;while(S) dep++,S>>=1ll;
printf("%lld
",Getans(dep,1,n));return 0;
}