• 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
    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    数据结构杂谈(三)堆排序
    数据结构杂谈(二)简单有趣的地精排序Gnome sort
    搭建proftp服务器
    python 单例模式
    mongo
    kafka
    查看端口占用
    tinyproxy 代理使用
    Linux 搭建wiki
    linux 安装 java
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5053824.html
Copyright © 2020-2023  润新知