#6469. Magic(01Trie)

这个按位贡献为1计算的方法真是秒啊。

考虑枚举 1 , 10 , 100 , … , 1 0 m 1,10,100,\dots,10^m 1,10,100,,10m的贡献。

计算对于 a i a_i ai 异或和 ≥ 1 0 m \ge 10^m 10m的个数,那么这一位的贡献就是 a n s ans ans

最后求和即可。

举个例子:

10 ⊕ 1 = 11 10\oplus 1=11 101=11

贡献是 2 2 2

$xor\ge 10^0=1 $ 的贡献是 1 1 1

x o r ≥ 1 0 1 = 10 xor\ge 10^1=10 xor101=10的贡献是1。

至于如何算贡献,考虑Trie上贪心即可。

n u m = ( 1 0 x − 1 ) num=(10^x-1) num=(10x1) 当前位为 1 1 1,则只能不同边,保证异或值也为 1 1 1

// Problem: #6469. Magic
// Contest: LibreOJ
// URL: https://loj.ac/p/6469
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// Date: 2022-01-03 18:05:45
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=5e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = {402653189,805306457,1610612741,998244353};
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y){
	if(x<y) x=y;
}
template <typename T>
void cmn(T &x,T y){
	if(x>y) x=y;
}
//01-Trie
const int li=60;
ll w[20];
struct Trie{
#define il inline	
	il void init(){
		w[0] = 1;
		for(int i=1;i<=18;i++) w[i] = w[i-1]*10;
	}
	int son[N*li][2],sz[N*li],cnt;
	il void ins(ll x){
		int p=0;
		for(int i=li;~i;i--){
			int &s=son[p][x>>i&1];
			if(!s) s=++cnt;
			p=s;
			sz[p]++;
		}
	}
	il int que(ll x,ll y){
		int p=0,ans=0;
		for(int i=li;~i;i--){
			int u=x>>i&1,v=y>>i&1;
			if(v){
				p = son[p][u^1];
			}
			else{
				ans+=sz[son[p][u^1]];
				p = son[p][u];
			}
			if(!p)break;
		}
		return ans;
	}
}T;
ll a[N];
int main(){
	int n;
	T.init();
	scanf("%d",&n);
	rep(i,1,n) scanf("%lld",&a[i]),T.ins(a[i]);
	ll ans = 0;
	rep(i,0,18)
		rep(j,1,n){
			ans+=T.que(a[j],w[i]-1);
		}
	printf("%lld\n",ans>>1);
	return 0;
}