题意:长度为n的序列a,每个区间价值为:该区间内所有的数相加.
1<=k<=n<=50, 0<a[i]<2^50,现在将序列a分成k段,要求这k段价值的AND结果最大.
从最高位x开始贪心,初始ans=0.
check:若前n个分成k段 并且每段的和 sum & (ans+2^x) 那么使ans+2^x 继续判断.
1<=k<=n<=50, 0<a[i]<2^50,现在将序列a分成k段,要求这k段价值的AND结果最大.
从最高位x开始贪心,初始ans=0.
check:若前n个分成k段 并且每段的和 sum & (ans+2^x) 那么使ans+2^x 继续判断.
判定时:设dp[i][j] 表示前i个分成j段 每段sum和ans+2^x 与运算是否为 ans+2^x. O(n^2*k*logS).
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=60+5;
ll n,k,a[N],p[N];
bool dp[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i],p[i]=a[i]+p[i-1];
ll res=0;
for(int bit=60;bit>=0;bit--)
{
ll ned=res+(1ll<<bit);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
if((p[i]&ned)==ned)
dp[i][1]=true;
for(int j=2;j<=k;j++)
{
for(int l=1;l<=i-j+1;l++)
{
ll sum=p[i]-p[i-l];
if((sum&ned)==ned && dp[i-l][j-1])
dp[i][j]=true;
}
}
}
if(dp[n][k]==true)
res=ned;
}
cout<<res<<'\n';
return 0;
}