UVA1607 Gates

这种题目。。。哎。。智商不够用啊。。由于输入只有一个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);
		else
			a=out[inp1[i]];
		if(inp2[i]<0)
			b=(-inp2[i]<=k);
		else
			b=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;
				else
					R=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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值