Description

巴厘岛的一条主干道上共有 N 座雕塑,依次编号为 1 到 N。雕塑 i 的年龄为 Yi​​ 。
政府想把这些雕塑分成恰好 X 组,要求 A≤X≤B。每组不能为空,且每组雕塑的编号必须连续。每个雕塑必须属于某一组。
分组方案需要考虑美观程度。计算方法如下:分别计算每组雕塑的年龄之和,然后将每一组的结果按位取或,就得到了该分组方案的美观值。
求最小的美观值。
对于71%的数据,【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_#include
对于另29%的数据,【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_#define_02

Solution

这题分了两档数据,各有特点,需要分开来考虑。

考虑【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_#define_03的情况
不妨从高到低逐位确定答案,假设我们已经确定完了前t-1位,需要确定第j位,我们可以先假设第j位为0,然后跑DP。设【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_#include_04表示前i个数分成了j组,每组和的或是否满足前j位与答案的j位相比没有多出来某些位是1,这是个0/1状态

直接枚举转移即可。

对于【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_DP_05的情况,发现A=1
那么分的组数越小越好,设【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_#define_06表示前i个数最少分成多少组就能满足条件。
同样枚举转移即可。
注意2000*Yi最多是2^40位

时间复杂度【杂题】[LibreOJ #2886]【APIO2015】巴厘岛的雕塑【DP】【按位确定】_二进制按位确定_07

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 2005
#define M 105
#define LL long long
using namespace std;
int n,a[N],L,R,g[N];
LL cf[41];
bool f[M][M];
int main()
{
cin>>n>>L>>R;
cf[0]=1;
fo(i,1,40) cf[i]=cf[i-1]<<1;
fo(i,1,n) scanf("%d",&a[i]);
if(n<=100)
{
LL s1=0;
fod(t,40,0)
{
bool pd=0;
memset(f,0,sizeof(f));
f[0][0]=1;
fo(i,1,n)
{
fo(k,1,i)
{
LL v=0;
fod(j,i,1)
{
v+=a[j];
if((((v>>t)<<t)|s1)!=s1) continue;
f[i][k]|=f[j-1][k-1];
if(f[i][k]) break;
}
if(i==n&&L<=k&&k<=R&&f[i][k]) {pd=1;break;}
}
}
if(!pd) s1^=cf[t];
}
printf("%lld\n",s1);
}
else
{
LL s1=0;
fod(t,40,0)
{
bool pd=0;
memset(g,107,sizeof(g));
g[0]=0;
fo(i,1,n)
{
LL v=0;
fod(j,i,1)
{
v+=a[j];
if((((v>>t)<<t)|s1)!=s1) continue;
g[i]=min(g[i],g[j-1]+1);
}
if(g[n]<=R) {pd=1;break;}
}
if(!pd) s1^=cf[t];
}
printf("%lld\n",s1);
}
}