H - ZYB loves Xor I HDU - 5269

 

【 题目意思 】:

  给你一个长度为n的序列,选择其中两个元素(a b 和 b a 是两种选择) 将他们异或,求异或后的lowbit的和。

【 思路 】:

  一个数的lowbit为,第一个不为0的数前有k个0,则为2^k 。

  可以看到 lowbit 是二进制从右往左找第一个1的位置 ,(是从小往后找)。

  那么异或之后值为1 ,就是在这一位上,原数组中的两个数 同时存在0 和 1。

  所以只要从低位开始建字典树,当字典树的分叉同是有0和1 时 , 就是当前的lowbit。将这个值 乘以 分别存储的数的个数 就是答案。

【题解】 :

  

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>

#define ms(a, b) memset(a,b,sizeof(a))
#define fast ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define ull unsigned long long
#define rep(i, a, b)  for(ll i=a;i<=b;i++)
#define lep(i, a, b)  for(ll i=a;i>=b;i--)
#define endl '\n'
#define pii pair<int, int>
#define pll pair<ll, ll>
#define vi  vector<ll>
#define vpi vector<pii>
#define vpl vector<pll>
#define mi  map<ll,ll>
#define all(a)  (a).begin(),(a).end()
#define gcd __gcd
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound

#define ff first
#define ss second
#define test4(x, y, z, a) cout<<"x is "<<x<<"        y is "<<y<<"        z is "<<z<<"        a is "<<a<<endl;
#define test3(x, y, z) cout<<"x is "<<x<<"        y is "<<y<<"        z is "<<z<<endl;
#define test2(x, y) cout<<"x is "<<x<<"        y is "<<y<<endl;
#define test1(x) cout<<"x is "<<x<<endl;
using namespace std;
const int N = 1e5 + 10 ;
const int maxx = 0x3f3f3f ;
const int mod = 998244353 ;
const int minn = -0x3f3f3f ;
const int M = 2 * N ;
ll T, n, m ;
ll a[N] , Case ;
ll ba[32] ;
ll ans ;
ll son[ N*35 ][ 2 ],idx,cnt[ N*35 ] ;
void insert(ll n) {
    int p = 0 ;
    for ( int i =0 ;i<=30 ; i++ ){
        int u = (n>>i) & 1 ;
        if ( !son[p][u] ){
            son[p][u]  = ++ idx ;
            son[idx][0] = son[idx][1] = 0 ;    // 将字典树清空的办法 。 将新建的点的子节点全部变为0 
            cnt[idx] = 0 ;
        }
        p = son[p][u] ;
        cnt[ p ] ++ ;
    }
}
void dfs(int g,int deep ){
    int l = son[g][0],r = son[g][1] ;
    if ( cnt[l]==0 && cnt[r]==0 ) return ;
    if ( r && l ){
        ans = ( ( cnt[l]*cnt[r]*ba[deep]%mod ) + ans )%mod;
        dfs( l , deep+1 ); dfs( r , deep+1 );
    }else if ( l ){
        dfs( l ,deep+1  );
    }else {
        dfs( r ,deep + 1 );
    }
}
void solve() {
    cin>>n;
    ans = 0;
    idx = 0 ;
    son[0][0] = son[0][1] = 0 ;
    rep(i,1,n){
        cin>>a[i];
        insert(a[i]);
    }
    dfs(0,0);
    ans = ans*2 % mod;
//    printf("Case #%d: %d\n",Case,ans);
    cout<<"Case #"<<Case<<": "<<ans<<endl;
}

int main() {
    fast;
    ba[0] = 1;
    rep(i,1,30) ba[i] = ba[i-1] * 2 ;
    cin >> T ;
    Case = 1 ;
    while ( T-- ) {
        solve();
        Case ++;
    }
    return 0;
}
View Code

 

posted @ 2022-04-03 14:34  Pan_c  阅读(47)  评论(0)    收藏  举报