牛客小白月賽25 J.異或和之和

牛客小白月賽25 J.異或和之和

題目鏈接

題目描述

給一個數組,數組內有 個正整數。
求這些數任取3個數異或運算後求和的值。
也就是說,取一共 Cn3C_{n}^{3} 個三元組,計算這些三元組內部異或,之後求和。(具體操作可以見樣例描述)
由於該值可能過大,輸出其對 109+710^9+7 取模的值。

輸入描述:

第一行一個正整數 。
接下來有 個正整數 aia_i1ai10181≤a_i≤10^{18}

輸出描述:

任取三個數、三元組內部位異或後求和對取模的值。

示例1

輸入

4
3 4 5 6

輸出

10

看到異或就是明顯的位運算啦~
位運算的精髓就是用一個數組 cntcnt 存儲答案~
我們考慮三個數抑或和爲 11 的情況,只有兩種:0 0 10\ 0\ 11 1 11\ 1\ 1
那麼我們可以計算出答案每一位的 11 的種類,用排列組合即可
有兩個坑點:

  • 上面的排列組合是可以直接死算的,但是取模會有問題,我也是試了很多種寫法才弄對,所以還是建議寫一個求組合數的函數
  • 此坑點見代碼註釋
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll cnt[100]={0};
ll k,n,ans=0;
ll power(ll a,ll b){return b?power(a*a%mod,b/2)*(b%2?a:1)%mod:1;}
void f(ll k){
    ll pos=0;
    while(k){
        if(k&1) cnt[pos]++;//這裏寫成cnt[pos++]++;就錯了,應該是優先級的問題,我吐了🤮
        pos++;
        k/=2;
    }
}
main(){
    cin>>n;
    for(ll i=0;i<n;i++){
        cin>>k;
        f(k);
    }
    for(ll i=0;i<100;i++){
       ll p=((n-cnt[i])*(n-cnt[i]-1)*cnt[i]/2+cnt[i]*(cnt[i]-1)*(cnt[i]-2)/6)%mod;
       ans=(ans+power(2,i)*p)%mod;
    }
    cout<<ans;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章