cf-779E (拆位)
题目
Problem Description
Bob recently read about bitwise operations used in computers: AND, OR and XOR. He have studied their properties and invented a new game.
Initially, Bob chooses integer m, bit depth of the game, which means that all numbers in the game will consist of m bits. Then he asks Peter to choose some m-bit number. After that, Bob computes the values of n variables. Each variable is assigned either a constant m-bit number or result of bitwise operation. Operands of the operation may be either variables defined before, or the number, chosen by Peter. After that, Peter's score equals to the sum of all variable values.
Bob wants to know, what number Peter needs to choose to get the minimum possible score, and what number he needs to choose to get the maximum possible score. In both cases, if there are several ways to get the same score, find the minimum number, which he can choose.
Input
The first line contains two integers n and m, the number of variables and bit depth, respectively (1 ≤ n ≤ 5000; 1 ≤ m ≤ 1000).
The following n lines contain descriptions of the variables. Each line describes exactly one variable. Description has the following format: name of a new variable, space, sign ":=", space, followed by one of:
||
|-|
|Binary number of exactly m bits.|
|The first operand, space, bitwise operation ("AND", "OR" or "XOR"), space, the second operand. Each operand is either the name of variable defined before or symbol '?', indicating the number chosen by Peter. |
Variable names are strings consisting of lowercase Latin letters with length at most 10. All variable names are different.
Output
In the first line output the minimum number that should be chosen by Peter, to make the sum of all variable values minimum possible, in the second line output the minimum number that should be chosen by Peter, to make the sum of all variable values maximum possible. Both numbers should be printed as m-bit binary numbers.
Sample
input | output |
---|---|
3 3 a := 101 b := 011 c := ? XOR b |
011 100 |
5 1 a := 1 bb := 0 cx := ? OR a d := ? XOR ? e := d AND bb |
0 0 |
Note
In the first sample if Peter chooses a number 011, then a = 101, b = 011, c = 000, the sum of their values is 8. If he chooses the number 100, then a = 101, b = 011, c = 111, the sum of their values is 15.
分析
- 题目大概意思是这样:有n个二进制下的m位数,先输入n和m,接下来n行,输入的是每个变量的名称(一个字符串),之后可有两个输入格式:若直接是一个数,那么就代表那个变量的值就是这个数,否则输入一个简单的运算式子(字符串A+运算+字符串B),其中运算只会是“OR”“XOR”以及“AND”,A.B要可能是"?"也可能是一个之前出现过的变量名。所有式子中,"?"代表的是同一个值,我们要求出"?"的两个值,分别使得所有变量的和最大或最小。要是有多个答案,输出字典序最小的。
- 注意位数不超过 1000,所以说肯定不是用整型来记录,那么就可以考虑拆位,把每一位拆出来单独讨论。
- 还有,题目所涉及的“与”、“或”、“异或”对每一位的数都只是会影响到那一位上,对其他位上的数没有影响,那么我们只需枚举"?"的每一位(从1到n),看看这一位取什么值(要么是1,要么是0)时,所有变量这一位上的值得和最大或最小,就可以得出答案了。
- 我用了个map来记录每个变量的名字以及它的编号。
程序
#include <cstdio>
#include <string>
#include <iostream>
#include <map>
using namespace std;
int n,m,val[5010][1010],f[5010],ans[2][1010];
//f[] 0:直接被赋值 1:and 2:or 3:xor
string _s,a[5010],b[5010];
map <string , int> name;
int Get(string ss){return name[ss];}
int _check(int x,int y){ //"?" 的第 x 位为 y 时改位所有变量的和
int Sum=0,k=1,g[5010];
for (int i=1; i<=n; i++){
if (f[i]==0) Sum+=g[i]=val[i][x];
else{
int k1,k2;
if (a[i]=="?") k1=y; else k1=g[Get(a[i])];
if (b[i]=="?") k2=y; else k2=g[Get(b[i])];
if (f[i]==1) Sum+=g[i]=k1&k2;
if (f[i]==2) Sum+=g[i]=k1|k2;
if (f[i]==3) Sum+=g[i]=k1^k2;
}
}
return Sum;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++){
cin >>_s; name[_s]=i;
cin >>_s >>_s;
if (_s[0]=='0' || _s[0]=='1') for (int j=1; j<=m; j++) val[i][j]=_s[j-1]-'0';
else{
a[i]=_s;
cin >>_s; if (_s=="AND") f[i]=1; else if (_s=="OR") f[i]=2; else f[i]=3;
cin >>_s; b[i]=_s;
}
}
for (int i=1; i<=m; i++){
int q1,q2;
q1=_check(i,1);
q2=_check(i,0);
if (q1<q2) ans[0][i]=1,ans[1][i]=0;
else if (q1>q2) ans[0][i]=0,ans[1][i]=1;
else ans[0][i]=ans[1][i]=0;
}
for (int p=0; p<=1; p++){
for (int i=1; i<=m; i++) printf("%d",ans[p][i]);
printf("\n");
}
}