题解
此题涉及异或运算且算法标签中有bitmasks,可以想到将答案分解为二进制(经典同类题目:老鼠试毒)。而分解后判断是否可以满足当前二进制位需要用到dp。因为异或运算不满足最优子问题,无法在一开始使用最优性dp,此处为可行性dp。
状态:\(dp[i][j]\):前\(i\)本书放入\(j\)个书架是否(0/1)可以满足当前二进制位。
初始值:\(dp[0][0]=1\),其余为\(0\)。
转移方程:无。枚举第\(i\)本书所在书架的左端点,如果该区间和满足当前及答案中全部二进制位,且转移来的状态合法,则当前状态合法。
答案:合法二进制位权值和。
此外利用贪心思想,二进制位需从大到小枚举,优先满足权值较大的。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=55;
int a[N],dp[N][N],sum[N];
signed main()
{
int n,k,ans=0,qwq;//qwq:答案+当前二进制位
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++) {scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i];}
int logn=log(sum[n])/log(2)+1;//最高二进制位
for(int p=logn;p>=0;p--)
{
memset(dp,0,sizeof(dp)); dp[0][0]=1;
qwq=ans+(1ll<<p);
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
for(int l=1;l<=i;l++)
if((qwq&(sum[i]-sum[l-1]))==qwq && dp[l-1][j-1]) dp[i][j]=1;
ans+=dp[n][k]*(1ll<<p);
}
printf("%lld",ans);
return 0;
}