牛客练习赛77D
这个题看完后,很显然我们要通过枚举各个位上得数将复杂度降为log级的,因此就诞生了我的第一发交的
rep(i,1,n){
rep(j,0,29){
rep(l,j+1,29){
a[i]^=(1<<j);
a[i]^=(1<<l);
ans+=(upper_bound(b+1,b+1+m,a[i])-b)-(lower_bound(b+1,b+1+m,a[i])-b);
a[i]^=(1<<j);
a[i]^=(1<<l);
}
}
}
枚举两个异或相异的地方,然而没有侥幸,直接t了。
那么枚举两个地方是不行的,那麽枚举一个应该可以吧,对数组a中每一个数的每一位的异或后的数存起来,对数组b中每一个数的每一位异或后在存的数里面得到个数累加。
但在这其中会有重复计算和错误计算,如当a中每个元素和b的每个元素相同时,这个数每一位的异或值都会被重复计算,因此,最后ans要减去b中出现在a中的元素乘以位数。
然后对于一组(x,y),由于x,y的二进制只有两位不一样,因此这种方法会导致答案是加倍,因此最后要除二。
map<int,int>s,z;
n=read(),m=read();
rep(i,1,n){
tmp=read();
rep(j,0,29){
s[tmp^(1<<j)]++;
}
z[tmp]++;
}
ll ans=0;
rep(i,1,m){
tmp=read();
rep(j,0,29) {
ans+=s[tmp^(1<<j)];
}
ans-=30*z[tmp];
}
print(ans>>1);
然后仍是光荣tle,map实在是太慢了,我看到大佬都是手写哈希表,嗯,手写哈希还是快,然后就A了。
class Hash{
private:
int last[maxn],nxt[maxn],cnt=0;
int a[maxn],b[maxn];
public:
void insert(int x){
int t=x%N;
for(int i=last[t];i;i=nxt[i]){
if(x==a[i]){
b[i]++;
return;
}
}
a[++cnt]=x;b[cnt]=1;
nxt[cnt]=last[t];
last[t]=cnt;
}
int query(int x){
int t=x%N;
for(int i=last[t];i;i=nxt[i]){
if(a[i]==x) return b[i];
}
return 0;
}
}s,z;
int main(){
#ifndef ONLINE_JUDGE
freopen("in0.txt","r",stdin);
// freopen("2.out","w",stdout);
#endif
int tmp;
n=read(),m=read();
rep(i,1,n){
tmp=read();
s.insert(tmp);
rep(j,0,29){
z.insert(tmp^(1<<j));
}
}
ll ans=0;
rep(i,1,m){
tmp=read();
rep(j,0,29) {
ans+=z.query(tmp^(1<<j));
}
ans-=s.query(tmp)*30;
}
print(ans>>1);
return 0;
}