AtCoder Regular Contest 092 Two Sequences AtCoder - 3943 (二进制+二分)

Problem Statement

 

You are given two integer sequences, each of length Na1,…,aN and b1,…,bN.

There are N2 ways to choose two integers i and j such that 1≤i,jN. For each of these N2 pairs, we will compute ai+bj and write it on a sheet of paper. That is, we will write N2 integers in total.

Compute the XOR of these N2 integers.

 

Definition of XOR

 

Constraints

 

  • All input values are integers.
  • 1≤N≤200,000
  • 0≤ai,bi<228

Input

 

Input is given from Standard Input in the following format:

N
a1 a2  aN
b1 b2  bN

Output

 

Print the result of the computation.

Sample Input 1

 

2
1 2
3 4

Sample Output 1

 

2

On the sheet, the following four integers will be written: 4(1+3),5(1+4),5(2+3)and 6(2+4).

Sample Input 2

 

6
4 6 0 0 3 3
0 5 6 5 0 3

Sample Output 2

 

8

Sample Input 3

 

5
1 2 3 4 5
1 2 3 4 5

Sample Output 3

 

2

Sample Input 4

 

1
0
0

Sample Output 4

 

0


题意:
给你两个含有n个数的数组a,b
然后我们对每一个a[i] 加上 b[j] 得到的数,把这些数全部异或起来,问最后的异或值是多少?

思路:
首先我们对每一个数进行二进制拆分,对每一位进行讨论,
只需要讨论二进制的第x位,在所有相加出来得到的数中是奇数个还是偶数个,
如果是奇数个就对答案有贡献,贡献值为 1<<x,偶数个就没有贡献。
然后问题转化为 我们要咋知道 有多少对 a[i] + b[j] 的第x位为1

由于我们每一步只讨论a[i]+b[j] 的第x位,我们可以只看a[i] 和 b[j] 的 二进制后 x 位,
因为我们只需要考虑 x位的情况就知道了 a[i]+b[j] 的 第x位情况,
那么我们在枚举第x位的时候,把a,b数组对 2的x+1次方 取模 ,即可得到每个数的二进制后x位。

然后利用这个结论,
对于一对数 a[i] +b[j] = num, 如果我们想要num的二进制第x位为1,需要满足:
num <= a[i]+b[j] <2*num
3*num <= a[i]+b[j] < 4*num

这样我们就可以在每一次取模后的数组,对其中一个数组进行排序,然后利用二分找到满足条件的区间,
通过区间的长度相加以来判定最终的满足x位是1的数量的奇偶性,来判定 是否在答案上加上贡献。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int a[maxn];
int b[maxn];
int n;
int c[maxn];
int d[maxn];
int main()
{
    //freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
    //freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    gbtb;
    cin >> n;
    repd(i, 1, n)
    {
        cin >> a[i];
    }
    repd(i, 1, n)
    {
        cin >> b[i];
    }
    int base = 1;
    ll ans = 0ll;
    for (int i = 0; i <= 28; i++)
    {
        repd(j, 1, n)
        {
            c[j] = a[j] % (2 * base);
            d[j] = b[j] % (2 * base);
        }
        sort(d + 1, d + 1 + n);
        int num = 0;
        repd(j, 1, n)
        {
            int r = lower_bound(d + 1, d + 1 + n, 2 * base - c[j]) - d - 2;
            int l = lower_bound(d + 1, d + 1 + n, base - c[j]) - d - 1;
            num += r - l + 1;
            r = lower_bound(d + 1, d + 1 + n, 4 * base - c[j]) - d - 2;
            l = lower_bound(d + 1, d + 1 + n, 3 * base - c[j]) - d - 1;
            num += r - l + 1;
        }
        if (num & 1)
        {
            ans += 1ll * base;
        }
        base *= 2;
    }
    cout << ans << endl;


    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

 



上一篇:HDU4812 D-tree


下一篇:Gym - 101982B Coprime Integers (莫比乌斯反演)