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;
}
View Code

相关文章:

  • 2022-01-17
  • 2022-01-29
  • 2021-10-01
  • 2021-05-30
  • 2022-12-23
  • 2021-10-02
  • 2021-10-28
  • 2021-06-03
猜你喜欢
  • 2022-01-05
  • 2021-08-28
  • 2022-01-12
  • 2021-12-12
  • 2021-08-09
  • 2022-01-11
  • 2021-11-11
相关资源
相似解决方案