Solution

挺简单的一道题, 虽然带着异或的皮, 看起来很复杂, 但其实只要我们从二进制位考虑就不难了
因为题目所给的数据是
因此二进制位上最多也就 位, , 我们考虑能否有的做法
观察递推式
前面两个可以 完成不用管
重点是后面那个累加式子, 我们把它们拆开其实也就是

从贡献方面考虑, 异或只会留下和这个数二进制位上不同的那些位, 那么我们只需要统计二进制位的出现情况
然后对于当前数字, 如果二进制位是 , 那么前面该位为 的数字就有贡献
反之, 如果二进制位是 , 那么前面该位为 的数字就有贡献
贡献为

  • 表示前面的 数组中二进制第 位为 的数目
  • 表示前面的 数组中二进制第 位为 的数目
  • 表示前面的 数组中二进制第 位为 的数目
  • 表示前面的 数组中二进制第 位为 的数目

扫一遍统计即可, 因为比较懒, 时间比较宽裕, 下面做法复杂度

Code

/*
  autor: Kurisu
  2020年4月30日16:48:49
*/
#include<bits/stdc++.h>
using namespace std;

const long long inf = 1e18;
const int N = 1e6 + 5;
const double eps = 1e-10;
const int mod = 1e9 + 7;
typedef long long ll;

ll a[N], b[N];
ll ans[N];
ll sum1[64][2], sum2[64][2];
ll qpow(ll a, ll b) {
  ll res = 1;
  while(b) {
    if(b & 1) {
      res = res * a % mod;
    }
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}
int main() {
  int n;
  cin >> n;
  for(int i = 1; i <= n; i++) cin >> a[i];
  for(int i = 1; i <= n; i++) cin >> b[i];
  for(int i = 1; i <= n; i++) {
    ll p = ans[i - 1] + (a[i] ^ b[i]) % mod;
    for(int j = 0; j <= 32; j++) {
      if(a[i] & (1LL << j)) { // 该位为1
        p += qpow(2, j) * sum2[j][0] % mod;
      }
      else { // 该位为0
        p += qpow(2, j) * sum2[j][1] % mod;
      }
      //cout << j << ' ' << sum2[j][0] << ' ' << sum2[j][1] << "\n";
    }
    for(int j = 0; j <= 32; j++) {
      if(b[i] & (1LL << j)) { // 该位为1
        p += qpow(2, j) * sum1[j][0] % mod;
      }
      else { // 该位为0
        p += qpow(2, j) * sum1[j][1] % mod;
      }
    }
    ans[i] = p % mod;
    for(int j = 0; j <= 32; j++) {
      if(a[i] & (1LL << j)) {
        sum1[j][1]++;
      }
      else sum1[j][0]++;
    }
    for(int j = 0; j <= 32; j++) {
      if(b[i] & (1LL << j)) {
        sum2[j][1]++;
      }
      else sum2[j][0]++;
    }
  }
  for(int i = 1; i <= n; i++) {
    cout << ans[i] % mod << " \n"[i == n];
  }
  return 0;
}