題解:
首先我們要分析一下這個公式
舉個例子來看,假設A數組與B數組的元素個數都爲2。
不難發現每次求的答案就是
當然我們不能暴力,這樣時間複雜度是O(n^2)
因此我們需要考慮異或的定義:
我們把每一個數轉換成一個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的個數。
當枚舉到到第一位答案很明確就是 ,考慮每一位對答案的貢獻即可,比較容易理解。
當枚舉到第二位是,我們枚舉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; }
Rinne Love Xor——異或性質
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.