lowbit

树状数组(lowbit)

Time Limit:1000ms   Memory Limit:128MB

题目描述

这天,LYK在学习树状数组。

当它遇到一个叫lowbit的函数时有点懵逼。lowbit(x)的意思是将x分解成二进制,它的值就是,其中k是最小的满足(x & )>0的数。(&是二进制中的and运算)

LYK甚至知道lowbit(x)=(x&-x)。但这并没什么用处。

现在LYK有了n个数字,为了使自己更好的理解lowbit是什么意思。它想对所有n^2个二元组求lowbit。具体的,对于一个二元组(ai,aj),它的值为lowbit(ai xor aj) (xor表示异或的意思),那么总共有n^2对二元组,LYK想知道所有二元组的值加起来是多少。

这个答案可能很大,你只需输出这个值对1000000007取模后的结果就可以了。

输入格式(lowbit.in)
第一行一个数n,表示有n个这样的数字。

第二行n个数ai。

输出格式(lowbit.out)

一个数表示答案。

输入样例

5

1 2 3 4 5

输出样例

32

数据范围

对于30%的数据n<=1000。

对于另外10%的数据ai<=1。

对于再另外10%的数据ai<=3。

对于再再另外20%的数据ai<1024。

对于100%的数据1<=n<=100000,0<=ai<2^30。

  先说一下暴力的做法(只能拿70分);

分类处理

  对于前30%的数据,直接按照题目去做就行。

  接下来40%的,a[i]范围较小,开一个桶数组,记录每个数出现了多少次(因为n<=100000,而a[i]<=1024,每个数一定出现过多次,我们只算一次就行了)

  

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<math.h>
using namespace std;
#define M 1000000007
long long n,c;
int f[10205];
long long ans,o,maxn;
long long last=0,x,y,t;
long long     lowbit(long long x)
{
    return x&(-x);
}
int main()
{
    freopen("lowbit.in","r",stdin);
    freopen("lowbit.out","w",stdout);
    scanf("%lld",&n);
    if(n<=1000) //这里掉了个等号,调了好久。。。。
    {
        for(int i=1;i<=n;i++)
        scanf("%d",&f[i]);
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        o=lowbit((long long)f[i] ^ f[j]),ans=(ans+o)%M;
        ans=ans*2%M;
        cout<<ans;
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&c);
        f[c]++;maxn=max(maxn,c);
    }
    for(int i=0;i<=maxn;i++)
    for(int j=i+1;j<=maxn;j++)
    {
        t=(i ^ j);
        o=lowbit(t);
        ans=(ans+o*f[i]*f[j]%M)%M;
    }
    ans=ans*2%M;
    cout<<ans;
    return 0;
} 

满分的做法就要考虑lowbit 和二进制数的性质了。

  lowbit是指 某数在二进制中最后一个“1”所在位置的权值。

  两个数 xor(异或)的lowbit与 他们从低位到高位第一个不同位的权值有关。

思路

  (1)那么,我们就从低位向高位注意比较有多少个在这个位上是“1”,多少个是“0”。分别放在集合X,集合Y中。

  (2)那么对于任意a∈X,b∈Y,,    lowbit(a,b)就是这个位的权值。

  这样集合X和Y之间的lowbit就求出来了(集合X,Y内部的数的lowbit还没求),接下来就分别对集合X,Y内部的数,对下一位进行同样操作 (1)(2)

实现的算法可以是分治,也可以是trie树。

时间原因,分治和trie树的代码先待续。。

时间: 2024-09-21 21:51:21

lowbit的相关文章

Lowbit Sum 规律

Lowbit Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description long long ans = 0;for(int i = 1; i <= n; i ++)    ans += lowbit(i)lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数比

hdu_5618_Jam&#39;s problem again(cdq分治+lowbit)

题目链接:hdu_5618_Jam's problem again 题意: 给你n个点,每个点有一个坐标(x,y,z),找出有ans个点,3个坐标都比该点小,这个点的level就为ans,然后让你输出所有点的ans. 题解: 对于第一维,直接排序,后面两维的处理可以用线段树套lowbit,但空间用的很大,这里满足运用cdq分治的条件,所有用cdq分治套lowbit,常数很小. 注意相同点的处理. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(

POJ 2309 BST(树状数组Lowbit)

题意是给你一个满二叉树,给一个数字,求以这个数为根的树中最大值和最小值. 理解树状数组中的lowbit的用法. 说这个之前我先说个叫lowbit的东西,lowbit(k)就是把k的二进制的高位1全部清空,只留下最低位的1,比如10的二进制是1010,则lowbit(k)=lowbit(1010)=0010(2进制),介于这个lowbit在下面会经常用到,这里给一个非常方便的实现方式,比较普遍的方法lowbit(k)=k&-k,这是位运算,我们知道一个数加一个负号是把这个数的二进制取反+1,如-1

杂-lowbit

int lowbit(int x){ return x&(x^(x–1)); } int lowbit(int x){ return x&-x; }

[CF792D] Paths in a Complete Binary Tree (规律, 位运算, lowbit)

题目链接:http://codeforces.com/problemset/problem/792/D 画出树,找找规律,画图就好了.不算麻烦. 往下走的时候特判是不是叶子,往上走的时候特判是不是根.其余时候按照规律转移就是. 感觉可以推广到建树上,可以缩小常数是极好的. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 LL lowbit(LL x) { return x & (

(新人的第一篇博客)树状数组中lowbit(i)=i&amp;(-i) 的简单文字证明

第一次写博好激动o(≧v≦)o~~初一狗语无伦次还请多多指教 先了解树状数组http://blog.csdn.net/int64ago/article/details/7429868感觉这个前辈写的很好 但是里面提到的lowbit则是一笔带过,那么lowbit究竟是个什么鬼呢??? 首先明白一个概念,计算机中-i=(i的取反+1),也就是i的补码 而lowbit,就是求(树状数组中)一个数二进制的1的最低位,例如01100110,lowbit=00000010:再例如01100000,lowbi

Codeforces 327E Axis Walking (状压dp lowbit优化)

E. Axis Walking time limit per test:3 seconds memory limit per test:512 megabytes Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub lives at point 0 and Iahubina at point d. Iahub has n positive integ

ACdream 1154 Lowbit Sum (数位DP)

Lowbit Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description long long ans = 0; for(int i = 1; i <= n; i ++) ans += lowbit(i) lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数 比

ACDream - Lowbit Sum

先上题目: C - Lowbit Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description long long ans = 0;for(int i = 1; i <= n; i ++)    ans += lowbit(i)lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然

树状数组lowbit()函数原理的解释 x&amp;(x^(x-1)) x&amp;-x

树状数组lowbit()函数所求的就是最低位1的位置所以可以通过位运算来计算 树状数组通过 x&(x^(x-1)) 能够成功求出lowbit的原因: 首先设x=6,即110(2) 于是我们使 x-1=101 可以发现,当我们将一个二进制数减一时,从最低位一(即lowbit)开始向后的部分与之前全部相反,因为减去的1对后面的每一位都有影响,同时因为是二进制,影响就是让每一位都取反了 110 101 从最低位一(第二位)开始向后全部相反了 所以我们再与 x 异或一发,那么从lowbit开始往后全是1