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 MB
Submit: 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

Sample Output

1

posted on 2015-12-17 13:27  83131  阅读(173)  评论(0编辑  收藏  举报

导航