• 嵊州D5T3 指令 program 神奇的位运算


    指令 program

    【问题描述】

    krydom 有一个神奇的机器。

    一开始,可以往机器里输入若干条指令: opt x 其中,opt 是 & | ^ 中的一种,0 ≤ x ≤ 1023 。

    对于 0 到 1023 的每一个数 m,机器会输出 m 按照指令依次运算后的结果。

    现在,krydom 往里面输入了 n 条指令,但是 zcysky 觉得 krydom naive, 只用 3 条指令就实现了和这 n 条指令一样的功能。

    由于 krydom 很菜,希望你们帮帮他,但是只需要输出 5 条以内的指令就行了。

    【输入格式】

    第一行包括一个整数 n,表示指令的个数。 接下来 n 行,每行一个字符 opt 和一个数字 x,表示 ans = ans opt x

    【输出格式】

    第一行输出一个整数 m,表示有 m 条新指令。(要求 m ≤ 5)

    接下来 m 行,每行一个字符 opt 和一个数字 x。表示一条新指令。

    【输入输出样例】

    Input1 Input2 Input3

    3

    | 3

    ^ 2

    | 1

    3

    &1

    & 3

    & 5

    3

    ^ 1

    ^ 2

    ^ 3

    Output1 Output2 Output3

    2

    | 3

    ^ 2

    1

    & 1

    0

    【样例解释】

    样例 2 解释:

    ((x&1)&3)&5 = x&(1&3&5) = x&1

    样例 3 解释:

    ((x^1)^2)^3 = x^(1^3^4) = x^0 = x

    【数据范围】

    对于 20% 的数据满足: n ≤ 5 。

    对于 50% 的数据满足: x ≤ 3 。

    对于 100%的数据满足: n ≤ 5*10^5

    吐槽

    这是道使人有很多想法的题目呢

    当我看到位运算是,我想到的是<bitset>……------------STL大法好!

    后来,发现不需要那些高级函数和类方法,反倒觉得是搜索

    因为我只要从一个数出发,能通过三种运算,得到最终结果即可

    DFS

    #include<bits/stdc++.h>
    using namespace std;
    char opt1,opt2[6];
    int first=1023;
    int num2[6],ch=first,flag=0;//ch:目标状态 
    void dfs(int nowch,int depth){//nowch:dfs现在状态 
        if(depth>5) return;//(要求m ≤ 5)
        if(flag==1) return;
        //是否成功 
        if(ch==nowch) {
            cout<<depth<<endl;
            for(int i=0;i<depth;i++)
                cout<<opt2[i]<<" "<<num2[i]<<endl; 
            flag=1;
            return;
        } 
        //三种方法
        for(int i=1;i<=1023;i++){
            num2[depth]=i;
            opt2[depth]='&';
            dfs(nowch&i,depth+1);
            opt2[depth]='|';
            dfs(nowch|i,depth+1);
            opt2[depth]='^';
            dfs(nowch^i,depth+1);
            num2[depth]=0;
        }
        return;
    }
    int main(){
    //    freopen("program.in","r",stdin);
    //    freopen("program.out","w",stdout);
        int n; cin>>n;
        int num1[n],ans=n;
        for(int i=0;i<n;i++) {
            cin>>opt1;
            cin>>num1[i];    
            if(opt1=='&')
                ch&=num1[i]; 
            if(opt1=='|')
                ch|=num1[i];
            if(opt1=='^')
                ch^=num1[i];
        }
        dfs(first,0); 
        return 0;
    } 

    后来发现,DFS可以是可以,但是那个first不能仅仅是一个数

    否则,除了一些特殊解,得到的答案可能是错的(非常错!错到离谱!)

    因为没有人知道,那台机器到底是按哪个数作为标准的

    何况,它会把1到1023(1111111111)全输出

    按道理说吧,那基础的几十分总是能拿到的吧?

    但是,dfs最大的敌人,就是还没搜到就超时了。。。

    于是,我们就惊讶的看到了std。。。

    std

     1 #include <cstdio>
     2 #define FOR(i, l, r) for(int i = l; i <= r; ++i)
     3 using namespace std;
     4 int n, x, y, opt, f[11];
     5 char s[5];
     6 //用来表示 and& or| xor^ 
     7 int work(int now, int opt)
     8 {
     9     if (opt == 1) return 0;//如果是&,返回0 
    10     if (opt == 2) return 1;//如果是|,返回1 
    11     if (now <= 1) return now ^ 1;//如果now小于等于1,返回now对1按位异或 
    12         else return 5 - now;//now大于1,返回0101-now 
    13 }
    14 int output(int x)
    15 {
    16     int ans = 0;//每次输出结果先归0 
    17     for(int i = 10; i; --i)
    18     {
    19         ans <<= 1;//每次把ans左移一位,差不多相当于是自乘2 (0左移一位(或者说是*2)还是0哟) 
    20         if (f[i] == x) ans |= 1;//如果f[10~1]等于x(输进来的数),就把ans按位或于1,即把最低位变成1 
    21     }
    22     return ans;
    23 }
    24 int main()
    25 {
    26 //    freopen("program.in", "r", stdin);
    27 //    freopen("program.out", "w", stdout);
    28     
    29     FOR(i, 1, 10) f[i] = 2;
    30     scanf("%d", &n);
    31     FOR(i, 1, n)
    32     {
    33         scanf("%s%d", s, &x);//输入 
    34         if (s[0] == '&') opt = 1; else//分别用1,2,3来存储& | ^ 
    35         if (s[0] == '|') opt = 2; else opt = 3;
    36         FOR(j, 1, 10)
    37         {
    38             y = x & 1;//把x与1按位与的值赋给y 
    39             if (opt == 1 && !y) f[j] = work(f[j], 1);
    40             if (opt != 1 && y) f[j] = work(f[j], opt);
    41             x >>= 1;
    42         }
    43     }
    44     puts("3");//固定输出3,方便与三个符号都有操作 
    45     printf("& %d
    ", output(0) ^ 1023);//把结果与1111111111取按位异或 
    46     printf("| %d
    ", output(1));
    47     printf("^ %d
    ", output(3));
    48     //其实只要m<=5就好了,但是这是最简单的方法 
    49     return 0;
    50 }

    std的解析都在注释里了。

    因为这道题是SPJ,所以就算输出后面跟着的是0也行,不输出也行。

    这种方法也告诉我们,多种位运算是可以用三种位运算表示滴~

    有木有感觉很神奇?

  • 相关阅读:
    深度学习代码注解(一)—— mnistdeepauto
    只属于你我的共同记忆
    只属于你我的共同记忆
    道教的认识
    道教的认识
    作家、文学大家、大师的艺术风格
    作家、文学大家、大师的艺术风格
    视频、画面、语言、文字与脑海、心灵
    视频、画面、语言、文字与脑海、心灵
    URAL 1963 Kite 四边形求对称轴数
  • 原文地址:https://www.cnblogs.com/send-off-a-friend/p/11190268.html
Copyright © 2020-2023  润新知