zoukankan      html  css  js  c++  java
  • 牛客小白月赛29-B二进制

    牛客小白月赛29-B二进制

    题目描述:

    scimoon 有一个坏掉的计算器,这个计算器仅接受 (0sim 2^{20}-1) 的数

    这个计算器只支持一种操作,举个例子,输入一个数 x,这个数会按顺序进行 n 次操作,在第 i 次操作中,有一个操作符 (op_i)​ 和一个数 (a_i)

    如果 (op_i=1) 表示这次操作是将数 x 与 (a_i)​ 做 与运算

    如果 (op_i=2) 表示这次操作是将数 x 与 (a_i)​ 做 或运算

    如果 (op_i=3) 表示这次操作是将数 x 与 (a_i)​ 做 异或运算

    操作过后 x 将会变为运算的结果

    scimoon 觉得这个计算器非常地慢,于是他想对这 n 个运算做一些简化,这个艰巨的任务交给了你

    具体而言,你的任务是:用不超过 5 次上面的操作,使得对于任何 (0le xle 2^{20}-1),你的操作的输出与计算器的输出一致

    可以证明必然存在解

    可能存在多组解,你只需要输出一组可能的解即可

    输入描述:

    第一行一个整数 n,表示计算器的操作次数

    接下来 n 行,每行两个整数 op 与 a ,按顺序描述了每次操作

    输出描述:

    第一行一个 m,表示你的操作次数

    你必须保证你输出的 (mle 5)

    接下来 m 行每行仿照输入中 (op a) 的格式输出每次操作

    示例:

    输入

    1
    1 14514
    

    输出

    1
    1 14514
    

    备注

    (n leq 5×10^5,1 leq op leq 3,0 leq a leq 2^{20}−1)

    题解:

    位运算是可以有捷径的,分析可以发现,对于一个数位存在如下情况:

    • 与(&)运算对应位为1,原数位不变
    • 与(&)运算对应位为0,原数位为0
    • 或(|)运算对应位为1,原数位为1
    • 或(|)运算对应位为0,原数位不变
    • 异或(^)运算对应位为1,原数位取反
    • 异或(^)运算对应位为0,原数位不变

    所以我们只考虑可能改变数位的操作,即如下三种:

    • x&0 = 0
    • x|1 = 1
    • x ^1=!x

    因此我们只需要考虑每次操作的数的各个位数,和执行的运算:

    • 与运算,数位为0,之前所有操作无效,只需对该位执行&0操作
    • 或运算,数位为1,之前所有操作无效,只需对该位执行|1操作
    • 异或运算,数位为1,若上一异或位不为1,则执行一次^1操作,否则不执行
    代码:
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    int v[21][4];
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        int n;
        cin >> n;
        for(int i = 0; i < n; ++i) {
            int op, w;
            cin >> op >> w;
            for(int j = 0; j <= 20; ++j) {
                if(op == 1 && (w & 1) == 0) {
                    v[j][0] = 1;
                    v[j][1] = 0;
                    v[j][2] = 0;
                }
                else if(op == 2 && w & 1 == 1) {
                    v[j][1] = 1;
                    v[j][0] = 0;
                    v[j][2] = 0;
                }
                else if(op == 3 && w & 1 == 1) {
                    if(v[j][2]) v[j][2] = 0;
                    else v[j][2] = 1;
                }
                w >>= 1;
            }
        }
        int a = 0, b = 0, c = 0;
        for(int i = 0; i < 20; ++i) {
            if(v[i][0]) continue;
            a += (1 << i);
        }
        for(int i = 0; i < 20; ++i) {
            if(v[i][1]) {
                b += (1 << i);
            }
        }
        for(int i = 0; i < 20; ++i) {
            if(v[i][2]) {
                c += (1 << i);
            }
        }
        printf("3
    1 %d
    2 %d
    3 %d
    ", a, b ,c);
        return 0;
    }
    
  • 相关阅读:
    POJ 1681 Painter's Problem(高斯消元法)
    HDU 3530 Subsequence(单调队列)
    HDU 4302 Holedox Eating(优先队列或者线段树)
    POJ 2947 Widget Factory(高斯消元法,解模线性方程组)
    HDU 3635 Dragon Balls(并查集)
    HDU 4301 Divide Chocolate(找规律,DP)
    POJ 1753 Flip Game(高斯消元)
    POJ 3185 The Water Bowls(高斯消元)
    克琳:http://liyu.eu5.org
    WinDbg使用
  • 原文地址:https://www.cnblogs.com/LeafLove/p/13982627.html
Copyright © 2011-2022 走看看