Title

CF1870B Friendly Arrays 题解

前言

这是一道大水题但我还是想了很久,主要考查选手对于位运算的理解。

正文

题目大意

已知有一个长度为 $n$ 的序列 $a$ 和一个长度为 $m$ 的序列 $b$,现在你可以选取任意的一个 $b_j$ 满足 $1\leq j\leq m$,并把所有的满足 $1\leq i\leq n$ 的 $a_i$ 和 $b_j$ 做按位或运算。已知变量 $x=a_1 \oplus a_2 \oplus \dots \oplus a_n$,请分别求出 $x$ 的最小值和最大值。

解题思路

我们可以把 $a$ 数组转化成二进制后近似的看作一个二维数组。易证,对于每一个 $b$ 数组中的元素,该元素可以把与它每一位相对应的且元素该位为 $1$ 的 $a_i$ 的这一位全部转化为 $1$,如下图所示: 由此可以知道,对于 $n$ 为偶数的 $a$ 数组,其 $x$ 的最大值为原本数组中所有元素的异或和,最小值为数组中的元素对于 $b$ 数组中的所有元素的按位或运算之和的按位或的值的异或和;同理,当 $n$ 为奇数时,最大值为运算后的异或和,最小值为原来的元素的异或和。

AC代码

#include<bits/stdc++.h>
using namespace std;
inline char gc() {
    static char buf[1 << 14], * p1 = buf, * p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 14, stdin), p1 == p2) ? EOF : *p1++;
}
inline void read(int& x) {
    x = 0; int f = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-') f = -f; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
    x = (f == -1 ? -x : x); return;
}
inline void put(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) put(x / 10);
    putchar(x % 10 + '0'); return;
}inline void write(int x) { put(x); putchar('\n'); }
#define N 200005
int n,m,ans,mint,maxt;
int a[N],b[N];
inline void work(){
    read(n),read(m);
    for(int i=1;i<=n;i++)
        read(a[i]);
    for(int i=1;i<=m;i++)
        read(b[i]);
        maxt=a[1];
    for(int i=2;i<=n;i++){
        maxt^=a[i];
    }mint=maxt;
    if(n%2==0){
        int huo=0;
        for(int i=1;i<=m;i++)
            huo|=b[i];
        mint=(a[1]|huo);
        for(int i=2;i<=n;i++){
            mint^=(a[i]|huo);
        }
    }else{
        int huo=0;
        for(int i=1;i<=m;i++){
            huo|=b[i];
        }maxt=a[1]|huo;
        for(int i=2;i<=n;i++){
            maxt^=a[i]|huo;
        }
    }
    put(mint),putchar(' '),write(maxt);
}
int main() {
    int T;read(T);
    while(T--) work();
    return 0;
}
posted @ 2023-09-22 14:33  UncleSam_Died  阅读(26)  评论(0)    收藏  举报  来源