这题还是很考验思维的,dp倒是很容易
如果采用状压把所有二进制位考虑进来倒是能搞
但是这数最大50位,GG~
然 后 我 就 在 想 可 不 可 以 从 高 位 一 位 一 位 来 贪 心 然后我就在想可不可以从高位一位一位来贪心 然后我就在想可不可以从高位一位一位来贪心
验 证 某 一 位 能 否 达 到 是 很 简 单 的 验证某一位能否达到是很简单的 验证某一位能否达到是很简单的
关 键 是 判 断 高 位 可 行 后 , 如 何 判 断 低 位 在 满 足 高 位 的 情 况 下 可 行 关键是判断高位可行后,如何判断低位在满足高位的情况下可行 关键是判断高位可行后,如何判断低位在满足高位的情况下可行
这个后效性把我难死了
但 是 啊 ! ! 与 操 作 是 具 有 可 叠 加 的 性 质 的 但是啊!!与操作是具有可叠加的性质的 但是啊!!与操作是具有可叠加的性质的
比 如 这 次 判 断 了 高 位 x 二 进 制 可 行 比如这次判断了高位x二进制可行 比如这次判断了高位x二进制可行
现 在 要 判 断 x − 1 位 二 进 制 在 满 足 x 位 二 进 制 可 行 的 情 况 下 是 否 可 行 现在要判断x-1位二进制在满足x位二进制可行的情况下是否可行 现在要判断x−1位二进制在满足x位二进制可行的情况下是否可行
很 简 单 , 那 这 次 d p 去 判 断 每 组 有 ( 1 < < x ) + ( 1 < < ( x − 1 ) ) 很简单,那这次dp去判断每组有(1<<x)+(1<<(x-1)) 很简单,那这次dp去判断每组有(1<<x)+(1<<(x−1))
如 果 成 功 , 答 案 加 上 ( 1 < < ( x − 1 ) ) 如果成功,答案加上(1<<(x-1) ) 如果成功,答案加上(1<<(x−1))
然 后 下 次 判 断 在 这 个 基 础 上 继 续 与 叠 加 判 断 然后下次判断在这个基础上继续与叠加判断 然后下次判断在这个基础上继续与叠加判断
至于DP判断,很多人用区间DP
其实线性dp完全更好理解吧的,不知道他们怎么想的,复杂度也不会差
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,k,a[52],ans,dp[52][52],pre[52];
bool isok( int x )//判断第x位
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++)//枚举物品
for(int j=1;j<=min(i,k);j++)//枚举组
{
for(int q=0;q<i;q++)//从前面的物品转移而来
{
if( (x&(pre[i]-pre[q]) )!=x ) continue;
dp[i][j]|=dp[q][j-1];
}
}
if( dp[n][k] ) return true;
return false;
}
signed main()
{
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i],pre[i]=pre[i-1]+a[i];
for(int i=60;i>=0;i--)
{
int temp=( (int)1<<i );
if( isok( ans|temp ) )
ans|=temp;
}
cout << ans;
}