记录编号 246062 评测结果 AAAAAAAAAA
题目名称 [APIO2015]巴厘岛的雕塑 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 1.067 s
提交时间 2016-04-04 21:55:22 内存使用 11.90 MiB
显示代码纯文本
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=2010;
bool f[maxn][maxn],g[maxn][maxn],del[maxn][maxn];
//del指一段区间和是否可取,g指一个dp决策是否可取
bool G[maxn];
int F[maxn];
//这里针对特殊数据改变DP方式,表示到当前位置最小分段的方案数
long long sum[maxn],ans;
int n,A,B,Maxk;
int main(){
    freopen("sculpture.in","r",stdin);
    freopen("sculpture.out","w",stdout);
    scanf("%d%d%d",&n,&A,&B);
    for(int i=1;i<=n;i++){
        scanf("%lld",&sum[i]);
        sum[i]+=sum[i-1];
    }
    if(A>1){
        for(int k=47;k>=0;k--){
            memset(f,0,sizeof(f));
            f[0][0]=true;
            for(int i=1;i<=n;i++)
                for(int j=0;j<i;j++)
                    for(int l=1;l<=B;l++)
                        if(!g[j][l-1]&&f[j][l-1]&&!((sum[i]-sum[j])&(1ll<<k))&&!del[j+1][i])
                            f[i][l]=true;
            
            bool flag=false;
            for(int l=A;l<=B;l++)
                if(f[n][l]&&!g[n][l])
                    flag=true;
            if(flag){
                for(int i=1;i<=n;i++)
                    for(int l=1;l<=B;l++)
                        if(!f[i][l])
                            g[i][l]=true;
                            
                for(int i=1;i<=n;i++)
                    for(int j=0;j<i;j++)
                        if((sum[i]-sum[j])&(1ll<<k))
                            del[j+1][i]=true;
            }
            else
                ans+=1ll<<k;
        }
    }
    else{
        for(int k=47;k>=0;k--){
            memset(F,127,sizeof(F));F[0]=0;
            for(int i=1;i<=n;i++)
                for(int j=0;j<i;j++)
                    if(F[j]!=2139062143&&!del[j+1][i]&&!G[j]&&!((1ll<<k)&(sum[i]-sum[j])))
                        F[i]=min(F[i],F[j]+1);
            
            bool flag=false;            
            if(!G[n]&&F[n]<=B)
                flag=true;
            
            if(flag==true){
                for(int i=1;i<=n;i++)
                    for(int j=0;j<i;j++)
                        if(F[i]>B)
                            G[i]=true;
                
                for(int i=1;i<=n;i++)
                    for(int j=0;j<i;j++)
                        if((1ll<<k)&(sum[i]-sum[j]))
                            del[j+1][i]=true;
            }        
            else        
                ans+=1ll<<k;
        }
    }
    printf("%lld\n",ans);
    return 0;
}