题目描述
给出一个数组,求每两个相邻的数进行操作n-1次后所有可能得出的数
操作如下
a
(
x
)
b
=
(
(
a
&
b
)
+
(
a
∣
b
)
)
>
>
1
a(x)b= ((a\ \&\ b) + (a\ |\ b))>>1
a(x)b=((a & b)+(a ∣ b))>>1
样例输入
4
1 4 3 2
样例输出
1 2
思路
因为
a
&
b
=
m
i
n
(
a
,
b
)
a\ \&\ b\ =\ min(a,\ b)
a & b = min(a, b),
a
∣
b
=
m
a
x
(
a
,
b
)
a\ |\ b\ =\ max(a,\ b)
a ∣ b = max(a, b)
所以
(
(
a
&
b
)
+
(
a
∣
b
)
)
>
>
1
=
(
a
+
b
)
>
>
1
((a\ \&\ b) + (a\ |\ b))\ >>\ 1 = (a\ +\ b)\ >>\ 1
((a & b)+(a ∣ b)) >> 1=(a + b) >> 1
DP
设
f
i
,
j
,
k
f_{i,j,k}
fi,j,k为合并
i
,
j
i, j
i,j区间,最终结果为
k
k
k的
0
/
1
0/1
0/1状态
因为数据给出
a
i
⩽
7
a_i\ \leqslant\ 7
ai ⩽ 7,所以平均值也小于等于7
所以状态只有0~7
看转移
枚举长度
l
e
n
len
len,左端点
l
l
l,则右端点
r
=
l
+
l
e
n
−
1
r = l + len - 1
r=l+len−1
枚举分割点
k
k
k,左区间的值
q
q
q,右区间的值
p
p
p
则
f
l
,
r
,
(
p
+
q
)
>
>
1
=
f
l
,
k
,
q
&
f
k
+
1
,
r
,
p
f_{l, r, (p + q) >> 1} = f_{l, k, q}\ \&\ f_{k + 1, r, p}
fl,r,(p+q)>>1=fl,k,q & fk+1,r,p
时间复杂度
O
(
n
3
∗
8
2
)
O(n ^ 3 \ * \ 8 ^ 2)
O(n3 ∗ 82)
时间复杂度应该是可以刚好过
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int A[2005], F[155][155][10];
int n, Maxx;
int main()
{
memset(F, 0, sizeof(F));
scanf("%d", &n);
Maxx = -1e9;
for(int i = 1; i <= n; ++i)
{
scanf("%d", &A[i]);
Maxx = max(Maxx, A[i]);
F[i][i][A[i]] = 1;
}
for(int k = 1; k <= n; ++k)
for(int i = 1; i <= n; ++i)
{
int j = i + k - 1;
for(int l = i; l < j; ++l)
for(int p = 0; p <= Maxx; p++)
for(int q = 0; q <= Maxx; q++)
if(F[i][l][p] && F[l + 1][j][q])
F[i][j][(p + q) >> 1] = 1;
}
for(int i = 0; i <= Maxx; ++i)
if(F[1][n][i])printf("%d ", i);
return 0;
}