标签:
第1行:1个数N,表示整数的数量。(2 <= N <= 50000)
第2 - N + 1行:每行个1数A[i](1 <= A[i] <= 10^18)
输出两两异或后取Lg(以10为底)并取整后的和。
首先建出二进制trie,然后由数据范围知log10(A[i] xor A[j])在0到19,可以枚举每个数和log10的每个取值在trie上查询出现次数
#include<cstdio> typedef long long i64; i64 _(){ i64 x=0; int c=getchar(); while(c<48)c=getchar(); while(c>47)x=x*10+c-48,c=getchar(); return x; } const int N=50007*65; int n; i64 a[50007]; int ch[N][2],sz[N],ptr=1; i64 ts[20],p10[20]; void ins(i64 x){ int w=1; for(int i=62;~i;i--){ int d=x>>i&1; if(!ch[w][d])ch[w][d]=++ptr; w=ch[w][d]; ++sz[w]; } } int find(i64 x,i64 y){ int s=0,w=1; for(int i=62;~i;i--){ int d1=x>>i&1,d2=y>>i&1; if(d2)s+=sz[ch[w][d1^d2^1]]; w=ch[w][d1^d2]; } return s; } int main(){ n=_(); for(int i=0;i<n;i++){ a[i]=_(); ins(a[i]); } p10[0]=1; for(int i=1;i<=18;i++)p10[i]=p10[i-1]*10; for(int i=0;i<n;i++){ for(int j=1;j<=18;j++)ts[j]+=find(a[i],p10[j]); } ts[19]=1ll*n*n-ts[18]; for(int i=18;i>1;i--)ts[i]-=ts[i-1]; ts[1]-=n; i64 ans=0; for(int i=2;i<=19;i++)ans+=(i-1)*ts[i]; printf("%lld",ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/ccz181078/p/5782369.html