BZOJ 3668 起床苦难综合症
看到这道题,分析后第一反应是取1的数最大的数,很明显我是忽略了 XOR 可以把0变成1的可能性。 后来想了想,又看了别人的题解后发现。这二进制的变换中每一位都是互相独立的,因为每一个数都只有两种初始状态和终止状态。即一开始为0的二进制位经过多次变换后可能为1或者为0, 为1的二进制位经过变换后也有可能变为1或0, 很明显,如果一开始为0的二进制位经过多次变换后变成了1,那么我们优先选择该二进制位的初始状态为0,如果不成立,如果一开始为1的二进制经过多次变换后可以变成1,且该数小于 m, 那么我们也可以将其初始状态设为1,若该二进制位无论0或1,最终都只是0,那么我们将其赋值为0.很显然,用两个数一个是0,一个是2的31次方减1, 去进行多次变换后看两者的值进行舍取得到最终的答案。
经验教训:
1:盲目认为0xfffffff 是2的31次方-1. WA了几次。
2:一开始在于初始状态为0的二进制位上认为要小于m,WA了几次。
心酸啊!
启发,有时候把一些复杂的题中各部分独立出来,一个个去解决。当然前提也是这道题中各部分不会相互影响。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #define rep(i,j,k) for(int i = j; i <= k; i++) 5 #define down(i,j,k) for(int i = j; i >= k; i--) 6 #define LL long long 7 using namespace std; 8 LL num = pow(2,31)-1; 9 LL num2 = 0; 10 11 int read() 12 { 13 int s = 0, t = 1; char c = getchar(); 14 while( !isdigit(c) ){ 15 if( c == '-' ) t = -1; c = getchar(); 16 } 17 while( isdigit(c) ){ 18 s = s * 10 + c - '0'; c = getchar(); 19 } 20 return s * t; 21 } 22 23 int main() 24 { 25 int n = read(), m = read(); 26 char c[5] = {0}; 27 rep(i,1,n){ 28 scanf("%s", &c); 29 int x = read(); 30 if( c[0] == 'A' ){ 31 num &= x; 32 num2 &= x; 33 } 34 if( c[0] == 'X' ){ 35 num ^= x; 36 num2 ^= x; 37 } 38 if( c[0] == 'O' ){ 39 num |= x; 40 num2 |= x; 41 } 42 } 43 LL ans = 0; 44 down(i,31,0){ 45 if( (num2 & (1<<i)) ){ 46 ans += (1 << i); 47 } 48 else if( (num & (1<<i)) && ((1<<i) <= m) ){ 49 m -= (1 << i); 50 ans += (1 << i); 51 } 52 } 53 cout<<ans<<endl; 54 return 0; 55 }
3668: [Noi2014]起床困难综合症
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1164 Solved: 660
[Submit][Status][Discuss]
Description
21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳。作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争。通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间。正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播。为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙。
历经千辛万苦,atm 终于来到了 drd 所在的地方,准备与其展开艰苦卓绝的战斗。drd 有着十分特殊的技能,他的防御战线能够使用一定的运算来改变他受到的伤害。具体说来,drd 的防御战线由 n扇防御门组成。每扇防御门包括一个运算op和一个参数t,其中运算一定是OR,XOR,AND中的一种,参数则一定为非负整数。如果还未通过防御门时攻击力为x,则其通过这扇防御门后攻击力将变为x op t。最终drd 受到的伤害为对方初始攻击力x依次经过所有n扇防御门后转变得到的攻击力。
由于atm水平有限,他的初始攻击力只能为0到m之间的一个整数(即他的初始攻击力只能在0,1,...,m中任选,但在通过防御门之后的攻击力不受 m的限制)。为了节省体力,他希望通过选择合适的初始攻击力使得他的攻击能让 drd 受到最大的伤害,请你帮他计算一下,他的一次攻击最多能使 drd 受到多少伤害。
Input
第1行包含2个整数,依次为n,m,表示drd有n扇防御门,atm的初始攻击力为0到m之间的整数。接下来n行,依次表示每一扇防御门。每行包括一个字符串op和一个非负整数t,两者由一个空格隔开,且op在前,t在后,op表示该防御门所对应的操作, t表示对应的参数。
Output
一行一个整数,表示atm的一次攻击最多使 drd 受到多少伤害。
Sample Input
3 10
AND 5
OR 6
XOR 7
AND 5
OR 6
XOR 7
Sample Output
1
————————————————