Rinne Love Xor——异或性质

题目链接:https://ac.nowcoder.com/acm/contest/5505/B

题解:

首先我们要分析一下这个公式

C_{i}=C_{i-1}+A_{i}\oplus B_{i}+\sum_{j=1}^{i-1}(A_{i}\oplus B_{j}+A_{j}\oplus B_{i})

举个例子来看,假设A数组与B数组的元素个数都为2。

C_{1}=A_{1}\oplus B_{1}

C_{2}=C_{1}+A_{2}\oplus B_{2}+A_{2}\oplus B_{1}+B_{2}\oplus A_{1} \Rightarrow C_{2}=A_{1}\oplus B_{1}+A_{2}\oplus B_{2}+A_{2}\oplus B_{1}+B_{2}\oplus A_{1}

不难发现每次求的答案就是\sum_{j=1}^{i} \sum_{k=1}^{i} A_{j}\oplus B_{k}

当然我们不能暴力,这样时间复杂度是O(n^2)

因此我们需要考虑异或的定义:0\oplus 1 = 1           1\oplus 0 = 1          1\oplus 1 = 0              0 \oplus 0 = 1

我们把每一个数转换成一个30位的二进制数考虑,那么对于A数组和B数组两个数的某一位而言,如果这两个数的相同位上,一个为0,一个为1,那么这个位就会对答案产生贡献。

我们可以考虑记录一下所有位上的0的个数和1的个数,

那么对于某个数某一位而言,对答案的贡献就是 cnt*(1<<i),i表示当前是第i位

cnt = A数组当前位上0的个数乘以B数组当前位上1的个数 + A数组当前位上1的个数乘以B数组当前位上0的个数

还是举个例子来说明一下。我们需要维护两个数组个A[j][0/1]和B[j][0/1]表示A数组(B数组)中第j位为0/1的个数。

当枚举到到第一位答案很明确就是 A_{1}\oplus B_{1},考虑每一位对答案的贡献即可,比较容易理解。

当枚举到第二位是,我们枚举A2与B2的每一位,对于第0位而讲,首先把A2与B2第0位的0/1的数加上去。

然后考虑A数组第0位为1的个数(包括之前第一位累加的)与 B数组第0位为0的的个数(包括之前第一位累加的)的乘积

相当于考虑的A1和A2第0位的0的个数和B1和B2第0位的1的个数乘积,这很显然是正确的。

假设A1与A2的第0位都是0,B1与B2第0位都为1,那么对答案的贡献就是4*(1<<i),即(1+1)*(1+1)*(1<<i)

剩下的类比一下就行了。

代码实现(比较简短):

#include<bits/stdc++.h>
#define rp(i,s,t) for(int i=s;i<=t;i++)
#define ll long long
using namespace std;
const ll mod = 1e9+7;
const int N = 1e5+7;
ll a[N],b[N],A[32][2],B[32][2];
int main(){
    int n;cin>>n;
    rp(i,1,n) cin>>a[i];
    rp(i,1,n) cin>>b[i];
    rp(i,1,n){
        ll res=0;
        rp(j,0,30){
            A[j][(a[i]>>j)&1]++;B[j][(b[i]>>j)&1]++;
            ll cnt=(A[j][0]*B[j][1]%mod+A[j][1]*B[j][0]%mod)%mod;
            res=(res+cnt*1ll*(1<<j)%mod)%mod;
        }
        cout<<res%mod<<((i==n)?"\n":" ");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值