题意
将序列分成 k 段,每一段段内贡献为各元素之和, 然后对各段贡献进行与运算,使得最终结果最大;
思路
从高到低计算每一位贡献,若该位 x 可以取 1 ,则 ans |= (1 << x), 而计算下一位时,判断 ans | (1 << (x - 1))是否能将序列分成 k 段即可;
判断方法可以用dp,f[i][j]表示前 j 个数能否分成 i 段;
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[55],sum[55];
int n,k;
ll f[55][55];
bool check(ll x){
memset(f,0,sizeof(f));
f[0][0]=1;
for(int i=1;i<=k;i++){
for(int j=i;j<=n;j++){
for(int k=i-1;k<j;k++){
if(!f[i-1][k]) continue;
if((x&(sum[j]-sum[k]))!=x) continue;
f[i][j]=1;
}
}
}
if(f[k][n]) return true;
return false;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i]; sum[i]=sum[i-1]+a[i];
}
ll ans=0;
for(int i=60;i>=0;i--){
ll tmp=(1ll<<i);
if(check(ans|tmp)) ans|=tmp;
}
cout<<ans<<"\n";
return 0;
}