题目大意自己看吧:
题解:
mx为所有val中最大的
1、如果n-k>log(mx)的话,就直接把所有数或起来就好了。
2、否则的话就DP,f[i][j]表示前i个和为j所用的最少数,这个很好DP,注意一下会爆空间,滚一下吧。(具体详见代码)
/*by cx_lzx*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
/*f[i][j]表示前i个和为j所用的最少数*/
int f[200000],g[200000];
int n,k;
int val[N],yu[20];
int mx=0;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&val[i]),mx=max(mx,val[i]);
if(n>k+log(mx)/log(2))
{
int ans=0;
for(int i=1;i<=n;i++) ans|=val[i];
// printf("!");
printf("%d\n",ans);return 0;
}
memset(f,inf,sizeof(f));f[0]=0;
memset(g,inf,sizeof(g));
yu[0]=1;
for(int i=1;i<=17;i++) yu[i]=yu[i-1]*2;
/* 爆空间版本
for(int i=0;i<=n-1;i++)
{
for(int j=0;j<=yu[17]-1;j++)
{
if(f[i][j]<inf)
{
f[i+1][j]=min(f[i][j],f[i+1][j]);
f[i+1][j|val[i+1]]=min(f[i+1][j|val[i+1]],f[i][j]+1);
}
}
}
int ans=0;
for(int i=yu[17]-1;i>=0;i--)
{
if(f[n][i]<=n-k)
{
ans=i;
break;
}
}*/
for(int i=0;i<=n-1;i++)
{
for(int j=0;j<=yu[17]-1;j++)
{
if(i%2==0)
{
if(f[j]<inf)
{
g[j]=min(f[j],g[j]);
g[j|val[i+1]]=min(g[j|val[i+1]],f[j]+1);
}
}
else{
if(g[j]<inf)
{
f[j]=min(f[j],g[j]);
f[j|val[i+1]]=min(f[j|val[i+1]],g[j]+1);
}
}
}
}
int ans=0;
if(n%2==0)
for(int i=yu[17]-1;i>=0;i--)
{
if(f[i]<=n-k)
{
ans=i;
break;
}
}
else
{
for(int i=yu[17]-1;i>=0;i--)
{
if(g[i]<=n-k)
{
ans=i;
break;
}
}
}
printf("%d\n",ans);
}
开学第一天就是周五,明天就可以回家了,然而所有课的老师全都在吹水。。。。。。
啥作业都没有,让我一度有些不适应。。。。。。。
又不敢整个晚修都来机房颓QAQ,在教室自习真的吓坏我QAQ。旁边那位大佬一直刷题,感觉都刷了30多页了,蒟蒻好方。