题目链接: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; }