CF981D Solution

题目链接

题解

此题涉及异或运算且算法标签中有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;
}
原文地址:https://www.cnblogs.com/violetholmes/p/14354585.html