印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道。
在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 1 到 N 连续地进行标号,其中第 i 座雕塑的年龄是 Yi 年。为了使这条路的环境更加优美,政府想把这些雕塑分成若干组,并通过在组与组之间种上一些树,来吸引更多的游客来巴厘岛。
下面是将雕塑分组的规则:
这些雕塑必须被分为恰好 X 组,其中 A< = X< = B,每组必须含有至少一个雕塑,每个雕塑也必须属于且只属于一个组。同一组中的所有雕塑必须位于这条路的连续一段上。
当雕塑被分好组后,对于每个组,我们首先计算出该组所有雕塑的年龄和。
计算所有年龄和按位取或的结果。我们这个值把称为这一分组的最终优美度。
请问政府能得到的最小的最终优美度是多少?
备注:将两个非负数 P 和 Q 按位取或是这样进行计算的:
首先把 P 和 Q 转换成二进制。
设 nP 是 P 的二进制位数,nQ 是 Q 的二进制位数,M 为 nP 和 nQ 中的最大值。P 的二进制表示为 pM−1pM−2…p1p0,Q 的二进制表示为 qM−1qM−2…q1q0,其中 pi 和 qi 分别是 P 和 Q 二进制表示下的第 i 位,第 M−1 位是数的最高位,第 0 位是数的最低位。
P 与 Q 按位取或后的结果是: (pM−1 OR qM−1)(pM−2 OR qM−2)…(p1 OR q1)(p0 OR q0)。其中:
0 OR 0=0
0 OR 1=1
1 OR 0=1
1 OR 1=1
输入的第一行包含三个用空格分开的整数 N,A,B。
第二行包含 N 个用空格分开的整数 Y1,Y2,…,YN。
从高到低枚举所有位,要使得对于每组该位最好都为0。
令dp[i][j]表示前i棵树分为j组是否能够满足条件。 枚举k,表示令k+1~j为一组。
满足条件当且仅当dp[k][j-1]满足条件且k+1~j为一组时满足当前所有位的条件。
时间复杂度为n^3*位数。
对于A=1的:
仍然从高到低枚举每一位。由于A=1的存在,我们可以令dp[i]表示前i个数在满足条件的情况下最少分为几组。
因此复杂度降为n^2*位数。
code:
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 typedef long long int64;
8 char ch;
9 bool ok;
10 void read(int &x){
11 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
12 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
13 if (ok) x=-x;
14 }
15 const int maxn=2005;
16 int n,a,b,v[maxn],g[maxn];
17 int64 sum[maxn];
18 bool f[205][205];
19 bool check(bool flag,int64 ans){
20 if (flag){
21 memset(g,63,sizeof(g));
22 g[0]=0;
23 for (int i=1;i<=n;i++) for (int j=0;j<i;j++) if (((sum[i]-sum[j])|ans)==ans) g[i]=min(g[i],g[j]+1);
24 return g[n]<=b;
25 }
26 else{
27 memset(f,0,sizeof(f));
28 f[0][0]=1;
29 for (int i=1;i<=n;i++) for (int j=1;j<=b;j++) for (int k=0;k<i;k++) if (((sum[i]-sum[k])|ans)==ans) f[i][j]|=f[k][j-1];
30 for (int i=a;i<=b;i++) if (f[n][i]) return true;
31 return false;
32 }
33 }
34 int main(){
35 read(n),read(a),read(b);
36 for (int i=1;i<=n;i++) read(v[i]),sum[i]=sum[i-1]+v[i];
37 int64 ans=(~0ULL>>1);
38 for (int i=62;i>=0;i--){
39 ans^=1LL<<i;
40 if (!check(a==1,ans)) ans^=1LL<<i;
41 }
42 printf("%lld\n",ans);
43 return 0;
44 }