1.与运算
 (点我)
 这个题的大概意思:给
    
     
      
       
        2
       
      
      
       2
      
     
    2个数
    
     
      
       
        n
       
      
      
       n
      
     
    n和
    
     
      
       
        x
       
      
      
       x
      
     
    x,其中满足
    
     
      
       
        n
       
       
        &
       
       
        (
       
       
        n
       
       
        +
       
       
        1
       
       
        )
       
       
        &
       
       
        (
       
       
        n
       
       
        +
       
       
        2
       
       
        )
       
       
        &
       
       
        (
       
       
        n
       
       
        +
       
       
        3
       
       
        )
       
       
        .
       
       
        .
       
       
        .
       
       
        &
       
       
        m
       
       
        =
       
       
        x
       
      
      
       n\&(n+1)\&(n+2)\&(n+3)...\&m=x
      
     
    n&(n+1)&(n+2)&(n+3)...&m=x,求最小的
    
     
      
       
        m
       
      
      
       m
      
     
    m,只要满足
    
     
      
       
        m
       
       
        >
       
       
        =
       
       
        x
       
      
      
       m>=x
      
     
    m>=x即可
 这个题在二进制的角度来看就是假设
    
     
      
       
        n
       
      
      
       n
      
     
    n的位是
100101
那么 x x x一定是从某一位开始与 n n n不同,并且不同的这一位(记为 q q q位)一定是 x x x为 0 0 0, n n n为 1 1 1;并且从这一位往右 x x x的位都是 0 0 0.只有这样才是满足条件的,假设不是这样。
- 情况一: x x x的 q q q位是为 1 1 1, n n n的为 0 0 0:一定不可能。与运算不可能弄出来一个 1 1 1
- 情况2: x x x从 q q q位往右还有 1 1 1:一定不可能。既然 x x x是累积与运算的结果,那么与到 q q q位一定是用一个 \space q + 1 q+1 q+1位(向左数1位)为 1 1 1后面都是 0 0 0的数 \space 与出来的。
综上所述, x x x的位可以是:
100100
在这里有一个
    
     
      
       
        t
       
       
        r
       
       
        i
       
       
        c
       
       
        k
       
      
      
       trick
      
     
    trick:
    
     
      
       
        n
       
      
      
       n
      
     
    n的
    
     
      
       
        q
       
       
        +
       
       
        1
       
      
      
       q+1
      
     
    q+1位为
    
     
      
       
        1
       
      
      
       1
      
     
    1.这个 
    
     
      
       
        q
       
       
        +
       
       
        1
       
      
      
       q+1
      
     
    q+1位(向左数1位)为
    
     
      
       
        1
       
      
      
       1
      
     
    1后面都是
    
     
      
       
        0
       
      
      
       0
      
     
    0的数 应该与
    
     
      
       
        n
       
      
      
       n
      
     
    n中
    
     
      
       
        q
       
       
        +
       
       
        1
       
      
      
       q+1
      
     
    q+1位(含)相加(造出
    
     
      
       
        m
       
      
      
       m
      
     
    m),但是如果
    
     
      
       
        n
       
      
      
       n
      
     
    n的
    
     
      
       
        q
       
       
        +
       
       
        1
       
      
      
       q+1
      
     
    q+1位为
    
     
      
       
        1
       
      
      
       1
      
     
    1,那么
    
     
      
       
        q
       
       
        +
       
       
        1
       
      
      
       q+1
      
     
    q+1位就会被消掉了。比如说
    
     
      
       
        n
       
       
        =
       
       
        3
       
      
      
       n=3
      
     
    n=3和
    
     
      
       
        x
       
       
        =
       
       
        2
       
      
      
       x=2
      
     
    x=2最后求出来
    
     
      
       
        m
       
      
      
       m
      
     
    m是
    
     
      
       
        4
       
      
      
       4
      
     
    4,结果是错的。证明略去。
 代码:
#include<iostream>
#include<cstdio>
#include<bitset>
typedef long long ll;
using namespace std;
typedef long long ll;
int main(void)
{
	int t;
	scanf_s("%d", &t);
	for (int i = 0; i < t; i++)
	{
		ll n, x;
		scanf_s("%lld%lld", &n, &x);
		bitset<100> n2;
		bitset<100> x2;
		n2 = n;
		x2 = x;
		int flag = 1;
		for (int i = 99; i >= 0; i--)
		{
			 
			if (x2[i] != n2[i]&&x2[i]==1&&n2[i]==0)
			{
				flag = 0;
				break;
			}
			else if (x2[i] != n2[i])
			{
				if (x2[i + 1] == 1)
				{
					flag = 0;
					break;
				}
				for (int j = i - 1; j >= 0; j--)
				{
					if (x2[j] != 0)
					{
						flag = 0;
						break;
					}
				}
				if (flag == 0)
					break;
				x2[i + 1] = 1;
				break;
			}
		}
		if (flag == 0)
			printf("-1\n");
		else
		{
			ll sum = 0;
			for (int i = 99; i >= 0; i--)
			{
				sum = sum * 2 + x2[i];
			}
			printf("%lld\n", sum);
		}
	     	
	}
}
2.或运算
 集合?(点我)
 这个题的大概意思是给
    
     
      
       
        n
       
      
      
       n
      
     
    n个数,然后每个数是以位的形式给出的,比如说第
    
     
      
       
        i
       
      
      
       i
      
     
    i个数有
    
     
      
       
        3
       
      
      
       3
      
     
    3位:
    
     
      
       
        2
       
       
        ,
       
       
        3
       
       
        ,
       
       
        5
       
      
      
       2,3,5
      
     
    2,3,5(
    
     
      
       
        2
       
       
        ,
       
       
        3
       
       
        ,
       
       
        5
       
      
      
       2,3,5
      
     
    2,3,5位上是
    
     
      
       
        1
       
      
      
       1
      
     
    1)那么第
    
     
      
       
        i
       
      
      
       i
      
     
    i行的样例就会给出:
3 2 3 5
现在要找出两个子序列,让他们的或运算的结果相等。
 我一开始想到集合上去了,就是把每个数的位加入到集合里面,然后看集合大小有没有变化,这个和加入顺序有很大关系,并且在某种程度是错误的:
 比如说:
3 1 3 4
3 2 3 1
3 3 5 2
这个样例其实是正确的,但是每次加入集合都有新元素,所以算法不对。实际上只要记录下来所有数的位的出现次数,然后再看是否存在一个数的所有位出现次数
    
     
      
       
        >
       
       
        1
       
      
      
       >1
      
     
    >1即可。
 数据结构:我之前交了个代码超时了,不是很理解 (用的
    
     
      
       
        v
       
       
        e
       
       
        c
       
       
        t
       
       
        o
       
       
        r
       
      
      
       vector
      
     
    vector,所以统计次数的那个位置使用了
    
     
      
       
        m
       
       
        a
       
       
        p
       
      
      
       map
      
     
    map
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
//const int length = 2e5 + 5;
int main(void)
{
	int t;
	scanf_s("%d", &t);
	for (int i = 0; i < t; i++)
	{
		int n;
		scanf_s("%d", &n);
		vector<vector<int>> edge(n);
	//	vector<int> c(length, 0);
		map<int, int> c;
		for (int i = 0; i < n; i++)
		{
			int k;
			scanf_s("%d", &k);
			for (int j = 0; j< k; j++)
			{
				int a;
				scanf_s("%d", &a);
				edge[i].push_back(a);
				c[a]++;
			}
		}
		int flag = 0;
		for (int i = 0; i < n; i++)
		{
			int yh = 1;
			//for (int j = 0; j < edge[i].size(); j++)
			for(int j:edge[i])
			{
				if (c[j] == 1)
				{
					yh = 0;
					break;
				}
			}
			if (yh == 1)
			{
				flag = 1;
				break;
			}
		}
		if (flag)
			printf("YES\n");
		else
			printf("NO\n");
	}
}

比较:
 
    
     
      
       
        1840
       
       
        m
       
       
        s
       
      
      
       1840ms
      
     
    1840ms是使用局部数组,在循环里用
    
     
      
       
        m
       
       
        e
       
       
        m
       
       
        s
       
       
        e
       
       
        t
       
      
      
       memset
      
     
    memset
 
    
     
      
       
        1855
       
       
        m
       
       
        s
       
      
      
       1855ms
      
     
    1855ms那个用的全局数组,然后在循环里用
    
     
      
       
        m
       
       
        e
       
       
        m
       
       
        s
       
       
        e
       
       
        t
       
      
      
       memset
      
     
    memset
 超时的是把二维数组移到全局,然后在循环里声明一个
    
     
      
       
        v
       
       
        e
       
       
        c
       
       
        t
       
       
        o
       
       
        r
       
      
      
       vector
      
     
    vector
 
    
     
      
       
        93
       
       
        m
       
       
        s
       
      
      
       93ms
      
     
    93ms是在循环里用
    
     
      
       
        m
       
       
        a
       
       
        p
       
      
      
       map
      
     
    map
 可能是开一个
    
     
      
       
        v
       
       
        e
       
       
        c
       
       
        t
       
       
        o
       
       
        r
       
      
      
       vector
      
     
    vector比较花时间,本来就是险过,但是用
    
     
      
       
        m
       
       
        a
       
       
        p
       
      
      
       map
      
     
    map就很快…



















