1275.
时间限制:1000MS内存限制:256000KB
题目描述
由于wangjp小学生数学题都不会做,给大家在考场上带来了很大的麻烦,他决心好好学习数学
本次他挑选了位运算专题进行研究 他发明了一种叫做“wangjp运算”的运算符:a$b =( (a&b) + (a|b) )>>1他为了练习,写了n个数在黑板上(记为a[i]) 并对任意相邻两个数进行“wangjp运算”,把两数擦去,把结果留下 这样操作n-1次之后就只剩了1个数,
这个数可能是什么?
将答案从小到大顺序输出
输入
输出
输入样例复制
4
1 4 3 2
输出样例复制
1 2
说明
Data Constraint 30% n<=10 0<=a[i]<=7 70% n<=150 0<=a[i]<=3 100% n<=150 0<=a[i]<=7
题解:观察可得该运算是求平均数,所以结果的集合为【0,7】,区间DP
f[i,j,0..7]表示[i,j]是否可以变为[0..7]中的数
枚举一个长度起点和断点,f[i,j,p]=f[i,k,p1] and f[k+1,j,p2] (p=(p1+p2)div 2)
错误做法:不能一个点一个点扩展状态,因为有可能两个区间结合在一起
const
maxn=200;
var
f:array[0..maxn,0..maxn,0..7]of longint;
a:array[1..maxn]of longint;
n,len,i,kk,k,j,p1,p2:longint;
procedure init;
var
i:longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[i]);
f[i,i,a[i]]:=1;
end;
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function check(x,y:longint):longint;
begin
check:=((x and y)+(x or y))shr 1;
end;
procedure gogo(i,j:longint);
var
k,kk,p1,p2,k1,k2:longint;
begin
for k:=i to j-1 do
begin
for k1:=0 to 7 do
if (f[i,k,k1]=1) then
for k2:=0 to 7 do
begin
kk:=(k1+k2)shr 1;
f[i,j,kk]:=max(f[i,k,k1] and f[k+1,j,k2],f[i,j,kk]);
end;
end;
{ for k:=0 to 7 do
begin
for kk:=0 to 7 do
begin
p1:=check(kk,a[i]);
p2:=check(kk,a[j]);
if p1=k then f[i,j,k]:=max(f[i+1,j,kk],f[i,j,k]);
if p2=k then f[i,j,k]:=max(f[i,j-1,kk],f[i,j,k]);
end;
end;}
end;
begin
init;
for len:=1 to n do
for i:=1 to n-len do
begin
j:=len+i;
gogo(i,j);
end;
for i:=0 to 7 do
if f[1,n,i]=1 then write(i,' ');
end.