树状数组(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 long
using 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 long
using 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;
}