lowbit

来源:互联网 发布:淘宝店铺招牌怎么上传 编辑:程序博客网 时间:2024/06/06 03:23

树状数组(lowbit)
Time Limit:1000ms Memory Limit:128MB

题目描述
这天,LYK在学习树状数组。
当它遇到一个叫lowbit的函数时有点懵逼。lowbit(x)的意思是将x分解成二进制,它的值就是2^k,其中k是最小的满足(x & 2^k)>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

读完题面
先看数据范围
n^2的纯暴力可以过30%的数据
常规的暴力分

然而
我们又注意到了

对于另外10%的数据ai<=1
对于再另外10%的数据ai<=3
对于再再另外20%的数据ai<1024

看起来很小啊
试试记录ai的数量
然后再进行暴力
lowbit(a[i] xor a[j])*num[a[i]]*num[a[j]]
这样的感觉

现在
我们能拿到70分了

之后的正解
我自己是想不出来啦……

以下引用

lowbit(x,y)
把x和y都分解成二进制
奇数(二进制末位是1),偶数(二进制末位是0)

lowbit(x^y)=1

把奇数放到左边,假设有x个
把偶数放到右边,假设有y个
x*y*2 对 lowbit起来是等于1

lowbit(x^y)=2
x和y全奇 或者 全偶
假如x和y全奇数
二进制倒数第二位一个是0一个是1
倒数第二位是0 倒数第二位是1

1 2 3 4 5
001 010 011 100 101

001 010
011 100
101

3*2*2 * 1 = 12

011 001         010 100
101

1*2*2 * 2 = 8      1*1*2 * 2=4

101 001
1*1*2 * 4 = 8

分治完之后, 二元组一个在左边,另一个在右边,这样的贡献是很容易统计的
对于每一个数,它只在最多31层中被分治到,总时间复杂度是n*31

正解

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<cmath>#include<queue>#include<vector>#include<climits>#include<string>#include<cstdlib>#include<ctime>#define MOD 1000000007#define MAXN 999999999#define LL long longusing namespace std;LL a[100005],b[100005],ans;LL n;void work(LL m,LL t){    LL l,r,p,i;    if(m<=1||t>=30) return;    l=0;    for(i=1;i<=m;i++)        if(a[i]&(1<<t))        {            l++;            b[l]=a[i];        }    r=l;    for(i=1;i<=m;i++)        if(!(a[i]&(1<<t)))        {            r++;            b[r]=a[i];        }    for(i=1;i<=m;i++) a[i]=b[i];    ans=(ans+(l*(m-l)%MOD)%MOD*(1<<t)%MOD)%MOD;    work(l,t+1);    p=0;    for(i=l+1;i<=r;i++)    {        p++;        a[p]=a[i];    }    work(p,t+1);}int main(){    freopen("lowbit.in","r",stdin);    freopen("lowbit.out","w",stdout);       int i;    scanf("%lld",&n);    for(i=1;i<=n;i++)        scanf("%lld",&a[i]);    work(n,0);    ans=(ans*2)%MOD;    printf("%lld",ans);    return 0;}

 
 
 
70

#include<iostream>#include<cstring>#include<algorithm>#include<cstdio>#include<cmath>#include<queue>#include<vector>#include<climits>#include<string>#include<cstdlib>#include<ctime>#define MOD 1000000007#define MAXN 999999999#define LL long longusing namespace std;LL n,x,num[100005],f[100005],k[100005],p,i,j,tmp,x1,x2,ans,maxn,nnn[100005];LL lowbit(LL emt){    return emt&(-emt);}int main(){    freopen("lowbit.in","r",stdin);    freopen("lowbit.out","w",stdout);       scanf("%lld",&n);    for(i=1;i<=n;i++)    {        scanf("%lld",&x);        nnn[i]=x;        maxn=max(maxn,x);        if(x<=1024)        {            num[x]++;            if(!f[x])            {                f[x]=1;                p++;                            k[p]=x;            }           }    }    if(maxn<=1024)    {        for(i=1;i<p;i++)            for(j=i+1;j<=p;j++)            {                x1=k[i];                x2=k[j];                tmp=2*lowbit(x1^x2)%MOD*(num[x1]%MOD*num[x2]%MOD)%MOD;                ans=(ans+tmp)%MOD;            }           }    else    {        for(i=1;i<=n;i++)            for(j=1;j<=n;j++)            {                tmp=lowbit(nnn[i]^nnn[j])%MOD;                ans=(ans+tmp)%MOD;            }    }    printf("%lld",ans);    return 0;}
原创粉丝点击