Rinne Loves Xor
题目描述:
输入描述:
第一行一个整数 N,表示数组 A 和 B 的长度。
第二行 N 个整数表示数组 A。
第三行 N 个整数表示数组 B。
输出描述:
输出一行 N 个整数,表示加密后的数组 C。
示例1
输入
10
65605 70259 77306 43823 61443 98602 9261 7662 46394 83019
81393 5966 61479 24259 92528 96132 35859 47981 11702 71736
输出
15796 166270 623824 1132402 1650729 2445262 3256941 4150718 5106184 6353038
备注
N<=1e5,ai<=1e9
解题思路:
题目数据1e5的n,那么n*n的算法就不行了,但是题目要求的运算时异或运算,那么在两组数据都在int范围内,那么就可以用一个数组记录到现在的位置每个数字二进制每一位上的数字数量,因为和每一个数字异或的和只需要计算a组的01数量和b组的01数量相乘的结果,因为是是在不同位置上的,所有需要乘上他们的权重,即左移相应的位数(如果要用位运算就需要知道位运算的优先级非常低),然后取模输出即可.
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
const int mod=1e9+7;
ll n,a[N],b[N],ba[55],bb[55];//长度,数组A,数组B,记录数组A的二进制数量,记录数组B的二进制数量
int main(){
ios::sync_with_stdio(false);
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
}
for(int i=0;i<n;i++){
ll c=0;
for(int j=0;j<=30;j++){//数据1e9到2的30次就够了
if((a[i]>>j)&1)ba[j]++;
if((b[i]>>j)&1)bb[j]++;
c=(c+((ba[j]*(i+1-bb[j])+bb[j]*(i+1-ba[j]))<<j))%mod;
}
cout<<c;
if(i==n-1)cout<<endl;
else cout<<" ";
}
}
return 0;
}