题目链接:http://codeforces.com/contest/981/problem/D
假设答案为ans,则一定从1走k步到n,每条边&ans的值为ans,边的权重为区间的和,然后贪心从高位枚举,如果这一位可以为1,则把这一位赋值为1,最后即可得到答案
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
typedef long long ll;
struct Edge
{
int v,nxt;
ll w;
}E[MAXN*MAXN];
int head[MAXN],tot;
ll a[MAXN],ans;
void init()
{
tot=0;a[0]=0;ans=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,ll w)
{
E[tot].v=v;E[tot].w=w;E[tot].nxt=head[u];
head[u]=tot++;
}
int n,k;
struct node
{
int now,st;
node(int _now=0,int _st=0):now(_now),st(_st){}
};
bool vis[MAXN][MAXN];
bool bfs(ll now)
{
queue<node> Q;
Q.push(node(1,0));
vis[1][0]=true;
memset(vis,false,sizeof(vis));
while(!Q.empty())
{
node T=Q.front();
Q.pop();
int id=T.now;
int st=T.st;
for(int i=head[id];~i;i=E[i].nxt)
{
int v=E[i].v;
if((E[i].w&now)!=now) continue;
if(!vis[v][st+1])
{
vis[v][st+1]=true;
Q.push(node(v,st+1));
}
}
}
return vis[n+1][k];
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
init();
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]+=a[i-1];
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n+1;j++)
addedge(i,j,a[j-1]-a[i-1]);
ll now=0;
for(int i=60;i>=0;i--)
{
now=ans|(1LL<<i);
if(bfs(now)) ans|=(1LL<<i);
}
printf("%lld\n",ans);
return 0;
}