Codeforces Round #443(Div.2) C.Short Program(位运算+思维)

题目链接:Short Program
题意:给出一段程序,这段程序只有与、或、异或三种操作,程序有n(n<=5e5)行,每行一个操作符,一个操作数。程序输入一个数,输出一个数。题目要求你设计一个<=5行的程序,使得 输入0~1023每个数在源程序得到的结果和在你设计的程序得到的结果是一样的。
思路:由于我们不知道输入的数是多少,只知道这个数<=1023,转化为二进制也就是<=1111111111。设计的程序的输出和原来的程序的输出结果一样,如果能保证结果的每一个二进制位一样,那么结果也一样。所以应该通过结果倒过来设计程序。输入未知,结果自然未知,但是我们不要忽略了输入和结果的每个二进制位都只会在0-1变化,这是入手的关键点。
我们这样来操作,得到每一位如果是0,n次操作过后的0-1结果,同样得到每一位如果是1,n次操作过后的0-1结果。即让0走一遍n次操作,让1023走一遍n次操作,我们就知道每一位是0-1时n此操作过后应该变成什么。那么也就是4中搭配嘛,①0->0, 1->1 ②0->1, 1->1 ③0->0, 1->0 ④0->1, 1->0。第一种就是操作前后不变嘛,不操作。第二种就是对应位或1操作,其他位或0不改变。第三种就是对应位与0操作,其他位与1不改变。第四种就是对应位异或1操作,其他位异或0不改变。至此,设计程序即可,最多就3行,与、或、异或各一行。

这样做复杂度还很低,貌似就是输入的复杂度O(5e5)。原创代码,头铁,思考花了点时间。

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define Max(a,b) a>b?a:b
#define Min(a,b) a>b?b:a
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
const double eps = 1e-6;
const double Pi = acos(-1.0);
const int INF=0x3f3f3f3f;
const int maxn = 5e5+10;
int zero[11], one[11];
int yu[11],huo[11],yihuo[11];
int main(){
    int n,d;
    char o;
    scanf("%d",&n);
    int a = 0, b = 1023;
    for(int i = 0; i < n; i++){
        getchar();
        scanf("%c %d",&o,&d);
        if(o == '|') a = a|d, b = b|d;
        else if(o == '^') a = a^d, b = b^d;
        else a = a&d, b = b&d;
    }
    int cnt = 1;
    while(a != 0){
        zero[cnt++] = a%2;
        a = a/2;
    }
    cnt = 1;
    while(b != 0){
        one[cnt++] = b%2;
        b = b/2;
    }

    for(int i = 1; i <= 10; i++) yu[i] = 1;
    bool op1 = false, op2 = false, op3 = false;
    for(int i = 1; i <= 10; i++){
        if(zero[i] == 0 && one[i] == 0) yu[i] = 0, op1 = true;
        else if(zero[i] == 1 && one[i] == 0) yihuo[i] = 1, op2 = true;
        else if(zero[i] == 1 && one[i] == 1) huo[i] = 1, op3 = true;
    }
    int ans = 0;
    int data[3];
    if(op1){
        ans++;
        data[0] = 0;
        for(int i = 1; i <= 10; i++){
            data[0] += yu[i]*pow(2,i-1);
        }
    }
    if(op2){
        ans++;
        data[1] = 0;
        for(int i = 1; i <= 10; i++){
            data[1] += yihuo[i] * pow(2,i-1);
        }
    }
    if(op3){
        ans++;
        data[2] = 0;
        for(int i = 1; i <= 10; i++){
            data[2] += huo[i] * pow(2,i-1);
        }
    }
    printf("%d\n",ans);
    if(op1) printf("& %d\n",data[0]);
    if(op2) printf("^ %d\n",data[1]);
    if(op3) printf("| %d\n",data[2]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值