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;
} 
京公网安备 11010502036488号