Rinne Loves Xor
题目描述
链接:https://ac.nowcoder.com/acm/contest/5505/B来源:牛客网
Rinne 最近学习了位运算相关的知识,她想运用自己学习的知识发明一个加密算法。
链接:https://ac.nowcoder.com/acm/contest/5505/B来源:牛客网
现在她想用程序来实现这个过程,你能帮帮她吗?由于输出可能太大,你只需要输出每个 \(C_i\) 模 10^9+7的结果即可。
输入描述:
第一行一个整数 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≤10^5,ai≤10^9
\(C_i\)这个式子,前两项都是可以O(1)算的。后面的项,考虑二进制每一位的贡献,相当于每次加上前i-1个\(B_i\)与当前数二进制位数字不同的所有位权和。
所以预处理一下\(A_i,B_i\),\(sum[i][j]\)表示前i位第j位是1的个数,不是1的个数就有\(i-sum[i][j]\)了,
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#define int long long
using namespace std;
const int N=100010,mod=1e9+7;
typedef long long LL;
int a[N],b[N],c[N],power[40],n;
int fa[N][40],fb[N][40];
void calc(int x,int a[]){
for(int i=0;i<=30;++i){
if(x&(1<<i)){
a[i]++;
}
}
}
signed main(){
power[0]=1;
for(int i=1;i<=30;++i){
power[i]=power[i-1]*2;
}
cin>>n;
for(int i=1;i<=n;++i) {
cin>>a[i];
calc(a[i],fa[i]);
for(int j=0;j<=30;++j){
fa[i][j]+=fa[i-1][j];
}
}
for(int i=1;i<=n;++i) {
cin>>b[i];
calc(b[i],fb[i]);
for(int j=0;j<=30;++j){
fb[i][j]+=fb[i-1][j];
}
}
for(int i=1;i<=n;++i){
c[i]=(LL)(c[i-1]+(LL)(a[i]^b[i])%mod)%mod;
for(int j=0;j<=30;++j){
if(!(a[i]&(1<<j))){
c[i]=(LL)(c[i]+(LL)fb[i-1][j]*power[j]%mod)%mod;
}
else {
c[i]=(LL)(c[i]+(LL)(i-1-fb[i-1][j])*power[j]%mod)%mod;
}
if(!(b[i]&(1<<j))){
c[i]=(LL)(c[i]+(LL)fa[i-1][j]*power[j]%mod)%mod;
}
else {
c[i]=(LL)(c[i]+(LL)(i-1-fa[i-1][j])*power[j]%mod)%mod;
}
}
}
for(int i=1;i<=n;++i){
cout<<c[i]<<" ";
}
return 0;
}