lowbit

来源:互联网 发布:mac install ipython 编辑:程序博客网 时间:2024/05/21 10:52

话说这道题跟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 ai<1024,我们用一个sum数组记录0-1024这些数出现的次数,然后,枚举数字这样就是1024^2可以过啦

#include <cstdio>#include <iostream>using namespace std;int sum[2000];int a[100011];const int mod=1000000007;int main(){    freopen("lowbit.in","r",stdin);    freopen("lowbit.out","w",stdout);    int maxf=-1e5;    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)     scanf("%d",&a[i]),maxf=max(maxf,a[i]);    if(maxf<=1024)     {        for(int i=1;i<=n;i++)         sum[a[i]]++;        long long ans=0;        for(int i=0;i<=maxf;i++)         for(int j=i+1;j<=maxf;j++)          {            int tmp=(i^j);            tmp=(tmp&-tmp);            ans=(ans+1ll*tmp*sum[i]*sum[j])%mod;          }        printf("%lld",ans*2%mod);     }     else     {        long long ans=0;        for(int i=1;i<=n;i++)         for(int j=1;j<=n;j++)         {          int w=a[i]^a[j];          if(j!=i) ans=(ans+(w&-w))%mod;         }        printf("%lld",ans%mod);     }     return 0;}

讲一下正解
lowbit(x,y),把x、y都分解成二进制,奇数二进制末位是1,偶数是0。

若要lowbit(x^y)=1,则需要末位不相同,即要求一个奇数和一个偶数搭配。

我们把所有的奇数归到一类放在左边,假设有x个;把所有的偶数放到右边,假设有y个。

则一共有xy2对lowbit(x,y)=1,贡献值为x*y2*1;

若要lowbit
(x^y)=2,则需要末位x和y全奇,或者全偶。并且倒数第二位两者不相同。

即在已经看过第一位的时候,再分别看末位为0和末位为1的两组(即奇数和偶数),

在其中的一组中,再次把他们分成倒数第二位为0,倒数第二位为奇的两组(即奇数和偶数)。

假设此时倒数第一位全是奇数的条件下,倒数第二位奇数有a个,偶数有b个,
则它的贡献为a*b2*2(末位为偶数也是这样)。
如果在要
lowbit(x^y)=4,则要在末位,倒数第二位相同的的情况下,在进行细分。

这样,一个分治的思路就体现出来了。

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

对于每一个数ai,我们求出有多少aj,
使得lowbit(ai^aj)=1
lowbit(ai^aj)=2
。。。。。。。
lowbit(ai^aj)=2^29

#include <cstdio>#include <iostream>using namespace std;const int mod=1000000007;int n;int a[100010];int b[100010];long long ans;void dfs(int n,int t){    if(n<=1||t>29) return;    int l=0;    for(int i=1;i<=n;i++)      if(a[i]&(1<<t)) b[++l]=a[i];    int r=l;    for(int i=1;i<=n;i++)     if(!(a[i]&(1<<t))) b[++r]=a[i];    for(int i=1;i<=n;i++) a[i]=b[i];     ans=(ans+(1ll*(1<<t)*(n-l)*l)%mod)%mod;    dfs(l,t+1);    int cnt=0;    for(int i=l+1;i<=r;i++)     a[++cnt]=b[i];    dfs(cnt,t+1);}int main(){    //freopen("lowbit.in","r",stdin);    //freopen("lowbit.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;i++)     scanf("%d",&a[i]);    dfs(n,0);    printf("%lld",ans*2%mod);    fclose(stdin);    fclose(stdout);    return 0;}