T1
从高到底按位确定答案
A=1时f[i]表示前i个数合法的划分至少需要分出几段,时间复杂度$O(n^2log(ans))$
A>1时f[i][j]表示前i个数划分为j段是否可能合法,转移显然,时间复杂度$O(n^3log(ans)/32)$
#include<cstdio> #include<cstring> #include<bitset> typedef long long i64; int n,A,B; int f[2007]; i64 s[2007],ans=0; std::bitset<207>d[207]; int main(){ scanf("%d%d%d",&n,&A,&B); for(int i=1;i<=n;++i)scanf("%lld",s+i),s[i]+=s[i-1]; if(A==1){ for(int x=50;x>=0;--x){ i64 v=ans|((1ll<<x)-1); for(int i=1;i<=n;++i){ f[i]=0x3f3f3f3f; for(int j=0;j<i;++j)if(((s[i]-s[j])|v)==v&&f[j]+1<f[i])f[i]=f[j]+1; } if(f[n]>B)ans|=1ll<<x; } }else{ d[0][0]=1; for(int x=50;x>=0;--x){ i64 v=ans|((1ll<<x)-1); for(int i=1;i<=n;++i){ d[i].reset(); for(int j=0;j<i;++j)if(((s[i]-s[j])|v)==v) d[i]|=d[j]<<1; } bool dd=0; for(int i=A;i<=B;++i)dd|=d[n][i]; if(!dd)ans|=1ll<<x; } } printf("%lld\n",ans); return 0; }