问题描述
给定数列{An}
求 lowbit( AixorAj )
其中,lowbit(x)=(x) and (-x)
输入格式
输出格式
样例输入
样例输出
数据范围
题解
Lowbit的含义是取出这个数字二进制下最低位的1
对于xor,当参加运算的两个数不同时为1
那么lowbit(AixorAj)就是取出二进制下不相同的最低位
如果是用模拟之类的算法,大概就是从低位到高位枚举找到两个数二进制下不相同的最低位。
然后就想到了字典树。。。
然而我做这题的时候完全忘了有字典树这种东西
由于是从低位到高位比较,把所有数字从低位到高位插入01字典树,记录每个结点被覆盖的次数,当一个数字走到某一个节点时,因为要求的是不相同的最低位,这个结点对答案是没有贡献的,他的兄弟结点对答案才有贡献。树上的节点都是01结点,仅仅取出结点被覆盖的次数是不够的,要根据结点的深度还原成原数。
1 #include <cstdio> 2 #define ll long long 3 const ll maxn=199907210507; 4 int n,cnt=1,f[12000015][2],num[12000015]; 5 ll a[100005],ans; 6 void add(ll x) 7 { 8 int now=1,i,j; 9 for (i=0;i<60;i++) 10 { 11 j=((x&(1ll<<i))>>i); 12 if (!f[now][j]) f[now][j]=++cnt; 13 num[f[now][j]]++; 14 now=f[now][j]; 15 } 16 return; 17 } 18 int main() 19 { 20 int i,j,k,now; 21 scanf("%d",&n); 22 for (i=1;i<=n;i++) 23 scanf("%lld",&a[i]); 24 for (i=1;i<=n;i++) add(a[i]); 25 for (i=1;i<=n;i++) 26 for (now=1,j=0;j<60;j++) 27 { 28 k=((a[i]&(1ll<<j))>>j); 29 ans=(ans+(1ll<<j)%maxn*num[f[now][k^1]]%maxn)%maxn; 30 now=f[now][k]; 31 } 32 printf("%lld\n",ans); 33 return 0; 34 }