去年的我对位运算一无所知。。所以在考场上直接没敢看题。。之后据说搜索有分,错的DP有分。我的内心是崩溃的。。然而就算看了题还是什么都不会写。
考虑按位贪心,从高位到低位枚举,用fi,j表示前i个数分成
然后O(n3)就可以轻松过点前4个
对于第5个
时隔半年多看这道题感觉还是挺水的嘛
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll s[2005],ans;
int n,a,b,B;
int g[2005],f[105][105];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline bool pd(ll t)
{
return (((t>>B+1)|ans)==ans&&(t>>B&1)==0);
}
int main()
{
n=read(); a=read(); b=read();
for (int i=1;i<=n;i++) s[i]=s[i-1]+read();
for (;1ll<<B<s[n];B++);
if (a!=1)
{
f[0][0]=1;
for (;~B;B--)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=min(i,b);j++)
{
f[i][j]=0;
for (int k=0;k<i&&!f[i][j];k++)
if (f[k][j-1]&&pd(s[i]-s[k])) f[i][j]=1;
}
int tmp=1;
for (int i=a;i<=b&&tmp;i++)
if (f[n][i]) tmp=0;
ans=ans<<1|tmp;
}
}
else
{
for (;~B;B--)
{
for (int i=1;i<=n;i++)
{
g[i]=n+1;
for (int k=0;k<i;k++)
if (pd(s[i]-s[k])) g[i]=min(g[i],g[k]+1);
}
ans=ans<<1|(g[n]>b);
}
}
cout << ans << endl;
return 0;
}