题目链接: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]);
}