题意
你有 本书,每本书有一个权值
.你要将这
本书分到
个书架上,要求你分组之后的每组权值之和的按位与的值最大。
思路
位运算啊,按位考虑。贪心的从高位到低位的使得此位值为
。我们就可以枚举最后的答案,从大到小,然后依次
一下。我们设计
方程:
。表示在前
个分为了
组是否成立,最后成立条件就是
。
代码
#include<bits/stdc++.h>
#define int long long
const int N=1e3+5,INF=0x3f3f3f3f,mod=998244353;
using namespace std;
int n,k,ans=0;
int w[N],sum[N];
int dp[N][N];
inline int read()
{
register int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
int qpow(int a,int b)
{
int ans=1;
while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}
return ans;
}
bool check(int x)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=k;i++)
for(int j=1;j<=n;j++)
for(int m=0;m<j;m++)
dp[i][j]|=dp[i-1][m]&(((sum[j]-sum[m])&x)==x);
return dp[k][n];
}
signed main()
{
n=read();k=read();
for(int i=1;i<=n;i++) w[i]=read(),sum[i]=sum[i-1]+w[i];
for(int i=60;i>=0;i--)
{
int mid=ans|(1LL<<i);
if(check(mid))
ans|=(1LL<<i);
}
printf("%lld",ans);
return 0;
}

京公网安备 11010502036488号