题意
你有 本书,每本书有一个权值 .你要将这 本书分到 个书架上,要求你分组之后的每组权值之和的按位与的值最大。
思路
位运算啊,按位考虑。贪心的从高位到低位的使得此位值为 。我们就可以枚举最后的答案,从大到小,然后依次 一下。我们设计 方程: 。表示在前 个分为了 组是否成立,最后成立条件就是 。
代码
#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; }