• 【积累】关于与或异或的一个积累


    关于与或异或的积累

    1,例题1

    题意:

    (n) 个操作: op a ,有 (3) 种:

    • (op_i=1) ,表示将 (x)(a_i) 做与运算;
    • (op_i=2) ,表示将 (x)(a_i) 做或运算;
    • (op_i=3) ,表示将 (x)(a_i) 做异或运算。

    要求将 (n) 个操作缩小成 小于等于 (5)个操作,使得对于任意 (x) ,进行这 (n) 个操作后的结果与 进行这 (m) 个操作的结果一致。

    其中 (0leq a_ileq2^{20}-1)

    解:

    先分别算出 (x_i=0)(x_i=1) 在这 (n) 个运算之后的结果。

    (x) 设置 (3) 种运算,例如 ((x&a)^b)|c 或者 ((x&a)|b)^c 等等;

    将二进制位的每一位独立开来看,然后对于 (x_i=0)(x_i=1) 进行 (n) 种运算之后的结果,设置对应的运算数值。

    例如 设置的运算时 ((x&a)^b)|c ,那么,

    (x_i=0)(x_i=1) 进行 (n) 种运算之后的结果分别是 (0)(0) ,可以设 (a_i=0)(b_i=0)(c_i=0) ;

    (x_i=0)(x_i=1) 进行 (n) 种运算之后的结果分别是 (0)(1) ,可以设 (a_i=1)(b_i=0)(c_i=0) ;

    (x_i=0)(x_i=1) 进行 (n) 种运算之后的结果分别是 (1)(0) ,可以设 (a_i=1)(b_i=1)(c_i=0) ;

    (x_i=0)(x_i=1) 进行 (n) 种运算之后的结果分别是 (1)(1) ,可以设 (c_i=1) ;

    其余同理。

    代码:

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mkp(a,b) make_pair(a,b)
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+5;
    
    int a[22],b[22];
    int main()
    {
    	for(int i=0;i<20;i++)a[i]=1;
    	int n,op,x,t,c;
    	scanf("%d",&n);
    	while(n--)
    	{
    		scanf("%d%d",&op,&x);
    		for(int i=0,c=0;i<20;i++,x>>=1,c++)
    		{
    			t=x&1;
    			if(op==1)a[c]&=t,b[c]&=t;
    			else if(op==2){
    				a[c]|=t;b[c]|=t;
    			}else{
    				a[c]^=t;b[c]^=t;
    			}
    		}
    	}
    	x=0;int y=0,z=0;
    	for(int i=0,t=1;i<20;i++,t<<=1)
    	{
    		if(a[i]==0&&b[i]==0);
    		else if(a[i]==1&&b[i]==0)x|=t;
    		else if(a[i]==0&&b[i]==1)x|=t,y|=t;
    		else if(a[i]==1&&b[i]==1)z|=t;
    	}
    	printf("3
    1 %d
    3 %d
    2 %d
    ",x,y,z);
    }
    
    

    2,例题2

    题意:

    给定 (n)(m)(2le n le10^5,0le mle 10^9) , $ x le m$

    (n) 个操作 :op a , 有 (3) 种:

    • (op_i=AND) ,表示将 (x)(a_i) 做与运算;
    • (op_i=OR) ,表示将 (x)(a_i) 做或运算;
    • (op_i=XOR) ,表示将 (x)(a_i) 做异或运算。

    询问最后可得到的最大值是多少。

    解:

    先分别算出 (x_i=0)(x_i=1) 在这 (n) 个运算之后的结果。

    答案要求最大,那么就是尽可能先让最终值的最高位为1:

    (x_i=0),而终值是 (1) 时 ,可以直接让答案 + (1<<i),因为 (x_i=0) ,不会影响 (x)(m) 的关系;

    否则,如果 (x_i=1) ,而终值也是 1,且对于当前 (m)(mge (1<<i)) ,则让答案+ (1<<i) ,且让 (m-=1<<i) 。(贪心)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    
    char s[5];
    int main()
    {
    	int n,m,x=0x7fffffff,y=0,v;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%s%d",s,&v);
    		if(s[0]=='A')x&=v,y&=v;
    		else if(s[0]=='O')x|=v,y|=v;
    		else x^=v,y^=v;
    	}
    	int res=0;
    	for(int i=30;i>=0;i--){
    		if(y&(1<<i))res+=1<<i;
    		else if(x&(1<<i)&&m>=(1<<i))m-=1<<i,res+=1<<i;
    	}
    	printf("%d
    ",res);
    }
    
  • 相关阅读:
    【转】extern "C"的含义和用法
    python的shelve库
    【转】TCP是流传输协议,UDP是包传输协议
    【转】TCP慢启动、拥塞避免、快速重传、快速恢复
    【转】C/C++多线程编程中什么情况下需要加volatile?
    【转】C++对象是创建在堆上,还是在栈上?
    【转】腾讯高级工程师:一道面试题引发的高并发性能调试思考
    【转】C++类的sizeof大小
    【转】C编译器内存对齐
    【转】c++中使用memset初始化类对象
  • 原文地址:https://www.cnblogs.com/kkkek/p/13976881.html
Copyright © 2020-2023  润新知