3668: [Noi2014]起床困难综合症
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 225 Solved: 153
[Submit][Status]
Description
Input
第1行包含2个整数,依次为n,m,表示drd有n扇防御门,atm的初始攻击力为0到m之间的整数。接下来n行,依次表示每一扇防御门。每行包括一个字符串op和一个非负整数t,两者由一个空格隔开,且op在前,t在后,op表示该防御门所对应的操作, t表示对应的参数。
Output
一行一个整数,表示atm的一次攻击最多使 drd 受到多少伤害。
Sample Input
AND 5
OR 6
XOR 7
Sample Output
HINT
【样例说明1】
atm可以选择的初始攻击力为0,1,...,10。
假设初始攻击力为4,最终攻击力经过了如下计算
4 AND 5 = 4
4 OR 6 = 6
6 XOR 7 = 1
类似的,我们可以计算出初始攻击力为1,3,5,7,9时最终攻击力为0,初始攻击力为0,2,4,6,8,10时最终攻击力为1,因此atm的一次攻击最多使 drd 受到的伤害值为1。
0<=m<=10^9
0<=t<=10^9
一定为OR,XOR,AND 中的一种
【运算解释】
在本题中,选手需要先将数字变换为二进制后再进行计算。如果操作的两个数二进制长度不同,则在前补0至相同长度。
OR为按位或运算,处理两个长度相同的二进制数,两个相应的二进制位中只要有一个为1,则该位的结果值为1,否则为0。XOR为按位异或运算,对等长二进制模式或二进制数的每一位执行逻辑异或操作。如果两个相应的二进制位不同(相异),则该位的结果值为1,否则该位为0。 AND 为按位与运算,处理两个长度相同的二进制数,两个相应的二进制位都为1,该位的结果值才为1,否则为0。
例如,我们将十进制数5与十进制数3分别进行OR,XOR 与 AND 运算,可以得到如下结果:
0101 (十进制 5) 0101 (十进制 5) 0101 (十进制 5)
OR 0011 (十进制 3) XOR 0011 (十进制 3) AND 0011 (十进制 3)
= 0111 (十进制 7) = 0110 (十进制 6) = 0001 (十进制 1)
Source
题解:
发现了一个比较好的性质,如果有一位or 1了就一定为1,所以不论之前的取值,如果有一位and 0了就一定为0
这样就只用考虑剩下的位了
考场上竟然sb的去枚举每一位(for i=1 to 1《《tot-1 do)。。。心里还想如果数据是随机的话,肯定需要枚举的位数不多。。。我太天真了。。。
其实想到这儿已经接近正解了,考虑到每一位互不影响,所以我们只单独枚举每一位,其他位都是0,来做一遍,看看能否为0,接下来就是sb贪心了
具体实现的时候,可以先用0做一遍,这样在枚举32位的时候,如果0得到的答案中这一位已经为1,那就不用考虑了,直接将这一位用0即可
代码:
1.考场80分(我还写了那么多小程序。。。)
1 var n,m,ans,x,y:int64; 2 i,j,tot,mark:longint; 3 a,b:array[0..1000000] of int64; 4 c:array[0..100] of boolean; 5 d:array[0..100] of int64; 6 ch:char; 7 flag:boolean; 8 procedure init; 9 begin 10 readln(n,m); 11 for i:=1 to n do 12 begin 13 read(ch);if ch='A' then b[i]:=1 else if ch='O' then b[i]:=2 else b[i]:=3; 14 while ch<>' ' do read(ch); 15 readln(a[i]); 16 if (b[i]=1) and (a[i]=0) then begin flag:=true;mark:=i;end; 17 end; 18 end; 19 procedure work1; 20 begin 21 ans:=0; 22 for j:=0 to m do 23 begin 24 x:=j; 25 for i:=1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 26 if x>ans then ans:=x; 27 end; 28 writeln(ans); 29 end; 30 procedure work2; 31 begin 32 x:=0; 33 for i:=mark+1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 34 writeln(x); 35 end; 36 procedure work4; 37 begin 38 x:=0; 39 for i:=1 to tot do inc(x,1<<(d[i]-1)); 40 for i:=1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 41 ans:=x; 42 for j:=1 to 500 do 43 begin 44 x:=random(m+1); 45 for i:=1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 46 if x>ans then ans:=x; 47 end; 48 writeln(ans); 49 end; 50 procedure work3; 51 begin 52 fillchar(c,sizeof(c),false); 53 for i:=1 to n do 54 if b[i]=2 then 55 for j:=1 to 32 do if (a[i] and (1<<(j-1))<>0) then c[j]:=true; 56 for i:=1 to n do 57 if b[i]=1 then 58 for j:=1 to 32 do if (a[i] and (1<<(j-1))=0) then c[j]:=true; 59 tot:=0; 60 for i:=1 to 32 do if not(c[i]) then begin inc(tot);d[tot]:=i;end; 61 y:=trunc(ln(m)/ln(2))+1; 62 while d[tot]>y do dec(tot); 63 if (1<<tot)*n>100000000 then begin work4;exit;end; 64 for i:=0 to 1<<tot-1 do 65 begin 66 x:=0; 67 for j:=1 to tot do 68 if i and (1<<(j-1))<>0 then inc(x,1<<(d[j]-1)); 69 if x>m then continue; 70 for j:=1 to n do if b[j]=1 then x:=x and a[j] else if b[j]=2 then x:=x or a[j] else x:=x xor a[j]; 71 if x>ans then ans:=x; 72 end; 73 writeln(ans); 74 end; 75 begin 76 assign(input,'sleep.in');assign(output,'sleep.out'); 77 reset(input);rewrite(output); 78 ans:=0; 79 flag:=false; 80 init; 81 if n*m<50000000 then work1 else if flag then work2 else work3; 82 close(input);close(output); 83 end.
2.正解100分
1 var n,m,ans,x,y,z,cnt:int64; 2 i,j,mark:longint; 3 a,b:array[0..1000000] of int64; 4 c:array[0..100] of boolean; 5 ch:char; 6 flag:boolean; 7 procedure init; 8 begin 9 readln(n,m); 10 for i:=1 to n do 11 begin 12 read(ch);if ch='A' then b[i]:=1 else if ch='O' then b[i]:=2 else b[i]:=3; 13 while ch<>' ' do read(ch); 14 readln(a[i]); 15 if (b[i]=1) and (a[i]=0) then begin flag:=true;mark:=i;end; 16 end; 17 end; 18 procedure work2; 19 begin 20 x:=0; 21 for i:=mark+1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 22 writeln(x); 23 end; 24 procedure work1; 25 begin 26 x:=0; 27 for i:=1 to n do if b[i]=1 then x:=x and a[i] else if b[i]=2 then x:=x or a[i] else x:=x xor a[i]; 28 z:=x;ans:=x;cnt:=0; 29 fillchar(c,sizeof(c),false); 30 for i:=31 downto 1 do 31 if z and (1<<(i-1))=0 then 32 begin 33 x:=1<<(i-1); 34 for j:=1 to n do if b[j]=1 then x:=x and a[j] else if b[j]=2 then x:=x or a[j] else x:=x xor a[j]; 35 if (x and (1<<(i-1))<>0) and (cnt+1<<(i-1)<=m) then begin c[i]:=true;inc(cnt,1<<(i-1));end; 36 end; 37 for i:=1 to 31 do if c[i] then inc(ans,1<<(i-1)); 38 writeln(ans); 39 end; 40 begin 41 assign(input,'sleep.in');assign(output,'sleep.out'); 42 reset(input);rewrite(output); 43 ans:=0; 44 flag:=false; 45 init; 46 if flag then work2 else work1; 47 close(input);close(output); 48 end.