Good Bye 2020 E

E. Apollo versus Pan

我们提取公因式
将原始转化为
∑j=1n ∑i=1n(xi&xj)⋅∑k=1n(xj|xk)
然后我们枚举j
我们考虑如何快速计算xj 与其他所有的| &的总和
显然我们可以按位考虑
对于| 要是我们该位xj为1我们其他所有就全都可以 为0就只能有其他所有该位为1的数才可以
对于& 我们显然要xj该位为1 其他所有为1 才可以算
就这样就可以快速计算出左右两边该位上的总和
注意 就是1<<j 这里的1是int 我们要用1ll才是ll

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 1e9+7;
#define int long long
int up(int a,int b){return a<0?a/b:(a+b-1)/b;}
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define pi acos(-1)
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

void solve() {
    int n;cin>>n;
    vector<int>a(n+10),v(100);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        for(int j=59;j>=0;j--){
            if(a[i]>>j&1){
                (++v[j])%=mod;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        int x=a[i];
        int l=0,r=0;
        for(int j=59;j>=0;j--){
            long long tmp=(1ll<<j)%mod;
            if(x>>j&1){
                (l+=(tmp%mod)*(v[j]%mod)%mod)%=mod;
                (r+=(tmp%mod)*(n%mod)%mod)%=mod;
            }else{
                (r+=(tmp%mod)*(v[j]%mod)%mod)%=mod;
            }
        }
        (ans+=l*r%mod)%=mod;
    }
    cout<<ans<<endl;
}
signed main(){
    fast
    int t;t=1;cin>>t;
    while(t--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-10-30 14:58  ycllz  阅读(20)  评论(0)    收藏  举报