UVA1607 Gates

来源:互联网 发布:mac os sierra剪贴板 编辑:程序博客网 时间:2024/05/10 09:53

这种题目。。。哎。。智商不够用啊。。由于输入只有一个x的值,所以电路无论多复杂,最终结果只有1,0,x或!x(所以可以这样理解,当电路的输出与x相关时,原电路一定可以等效为输入序列只有一个x其余均为0/1的情况)。取x为0与x为1,如果电路的输出结果相同,那么电路的输出结果一定是常数,那么随便输出一串0,1就行。。否则,由前面的讨论我们只需要找到那个填上x的位置,从全为0的输入开始,对于全为0的输入记其输出为a。每次将输入序列的第一个0替换为1。直到找到一个k使得输入序列的前k个数均为1时,该序列的输出结果不是a为止,那么我们的输入序列可以简化为111...1(k-1个1)x00000...(后面全是0)。因为对于全为1的输入序列,其输出不等于a所以符合条件的k一定存在,即这样的算法一定会给出答案。关于k的找法用二分,详见代码。

AC代码如下:(参考了编程。。毕竟我真的不会写这题。。)


#include <cstdio>using namespace std;int n,m,inp1[200005],inp2[200005],out[2000005];int calculate(int k)               //当输入序列的前k个数均为1时求电路的输出{for(int i=1;i<=m;i++){int a,b;if(inp1[i]<0)a=(-inp1[i]<=k);elsea=out[inp1[i]];if(inp2[i]<0)b=(-inp2[i]<=k);elseb=out[inp2[i]];out[i]=!(a&b);}return out[m];}int main(int argc, char const *argv[]){int T;scanf("%d", &T);while(T--){scanf("%d %d", &n, &m);for(int i=1;i<=m;i++)scanf("%d %d", &inp1[i],&inp2[i]);int x,y;x=calculate(0);y=calculate(n);if(x==y){for(int i=1;i<=n;i++)printf("0");printf("\n");}else{int L=0,R=n,mid=1;              //二分查找while(R-L>1){mid=(L+R)/2;if(calculate(mid)==x)L=mid;elseR=mid;}for(int i=1;i<=n;i++){if(i<R) printf("1");else if(i==R) printf("x");else printf("0");}printf("\n");}}return 0;}


0 0