[CSP-S模拟测试]:位运算(数学)

题目传送门(内部题72)


输入格式

  输入文件$bit.in$
  每个输入文件包含$T$组测试数据。输入文件的第一行为一个整数$T$,表示数据组数。接下来$T$行,每行表示一组测试数据每组测试数据包括三个空格隔开的数字 $ResultAnd,ResultOr,ResultXor$,依次表示对$a\&b,a|b,a\text{^}b$的限制。
  如果三项中某一项的数字为$-1$,那么说明对这一项没有限制。否则这一项的数字一定是一个非负整数,表示$a$和$b$进行这种运算后的结果。


输出格式

  输入文件$bit.out$
  $T$行,每行一个整数或一个字符串$"inf"$(不输出引号)。
  第$i$行的整数或字符串表示第$i$组测试数据的答案。


样例

样例输入:

10
20 1015 995
921 661 -1
-1 375 -1
30445634 30446311 30446245
11997588 11998143 555
-1 65535 -1
-1 465530605 312684161
2118209 930739953 928621744
69739040 402620388 332881348
4594346 533159678 528565332

样例输出:

128
0
2187
0
32
43046721
4096
32768
131072
4096


数据范围与提示

样例解释:

样例中$T=10$,且样例的第$i$行是来自第$(2*i-1)$个测试点的一组输入数据

数据范围:

对全部测试点:$T\leqslant 10,ResultAnd,ResultOr,ResultXor$都是$[-1,10^9]$区间内的整数。对同一组数据,$ResultAnd,ResultOr,ResultXor$不会均为$-1$。
第$1$到$5$个测试点:$0\leqslant ResultOr \leqslant 1023$
第$6$到$10$个测试点:$ResultOr-ResultAnd\leqslant 1000,ResultOr>=0,ResultAnd>=0$
第$11$到$16$个测试点:答案中不会出现$inf$
第$11$和$12$个测试点还满足:$ResultAnd=ResultXor=-1$
第$17,18$个测试点满足:不等于$inf$的答案不会超过$int$数据类型能表示的范围
第$19,20$个测试点:无特殊限制


题解

大力分类讨论即可。

位运算一定要先将其每位提取处理。

不妨设$a[i],b[i].c[i]$分别表示$\&,|,\text{^}$的每一位。

依次枚举:

  $\alpha.$都有限制:$ans=2^{\sum \limits_{i=1}^{30}a[i]\text{^}b[i]}$。

  $\beta.\&$没有限制:$ans=2^{\sum \limits_{i=1}^{30}b[i]\&c[i]}$。

  $\gamma.|$没有限制:$ans=2^{\sum \limits_{i=1}^{30}c[i]}$。

  $\delta.\text{^}$没有限制:$ans=2^{\sum \limits_{i=1}^{30}a[i]\text{^}b[i]}$。

  $\epsilon.$只有$\&$有限制:$ans=inf$。

  $\zeta.$只有$|$有限制:$ans=3^{\sum \limits_{i=1}^{30}b[i]}$。

  $eta.$只有$\text{^}$有限制:$ans=inf$。

时间复杂度:$\Theta(30\times T)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int AND,OR,XOR;
int a[50],b[50],c[50];
long long qpow(long long x,long long y)
{
	long long res=1;
	while(y)
	{	
		if(y&1)res=res*x;
		x=x*x;
		y>>=1;
	}
	return res;
}
int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int sum=0;
		scanf("%d%d%d",&AND,&OR,&XOR);
		if(AND!=-1&&OR==-1&&XOR==-1){puts("inf");continue;}
		if(AND==-1&&OR==-1&&XOR!=-1){puts("inf");continue;}
		if(AND!=-1&&OR!=-1&&XOR!=-1)
		{
			for(int i=0;i<=30;i++)
			{
				a[i]=(AND>>i)&1;
				b[i]=(OR>>i)&1;
				c[i]=(XOR>>i)&1;
				if(a[i]&&!b[i]){puts("0");goto nxt;}
				if(a[i]&&c[i]){puts("0");goto nxt;}
				if(!b[i]&&c[i]){puts("0");goto nxt;}
				sum+=a[i]^b[i];
			}
			printf("%lld\n",qpow(2,sum));
		}
		if(AND!=-1&&OR==-1&&XOR!=-1)
		{
			for(int i=0;i<=30;i++)
			{
				a[i]=(AND>>i)&1;
				c[i]=(XOR>>i)&1;
				if(a[i]&&c[i]){puts("0");goto nxt;}
				sum+=c[i];
			}
			printf("%lld\n",qpow(2,sum));
		}
		if(AND==-1&&OR!=-1&&XOR!=-1)
		{
			for(int i=0;i<=30;i++)
			{
				b[i]=(OR>>i)&1;
				c[i]=(XOR>>i)&1;
				if(!b[i]&&c[i]){puts("0");goto nxt;}
				sum+=b[i]&c[i];
			}
			printf("%lld\n",qpow(2,sum));
		}
		if(AND!=-1&&OR!=-1&&XOR==-1)
		{
			for(int i=0;i<=30;i++)
			{
				a[i]=(AND>>i)&1;
				b[i]=(OR>>i)&1;
				sum+=a[i]^b[i];
				if(a[i]&&!b[i]){puts("0");goto nxt;}
			}
			printf("%lld\n",qpow(2,sum));
		}
		if(AND==-1&&OR!=-1&&XOR==-1)
		{
			for(int i=0;i<=30;i++)
				sum+=(OR>>i)&1;
			printf("%lld\n",qpow(3,sum));
		}
		nxt:;
	}
	return 0;
}

rp++

posted @ 2019-10-18 06:04  HEOI-动动  阅读(262)  评论(0编辑  收藏  举报