UPC2022/3/18 晚训练赛补题

F:异或序列

题目描述

Venn有一个数列a1,a2,...,an。有一天,BLUESKY007拿来了一个正整数X。Venn是一个特别喜欢异或(xor)运算的孩子,她也很喜欢BLUESKY007。于是,Venn就想知道,自己能找到多少对数(i,j)能够满足aixoraj=X。两个数对(i1,j1)与(i2,j2)不同,当且仅当i1≠i2或者j1≠j2。

输入

第一行两个正整数n,X,分别表示数列的长度以及Bluesky带来的整数。
第二行包含n个正整数,表示数列{an}。

输出

一行一个整数表示答案。

样例输入 Copy

5 1
1 4 2 2 5

样例输出 Copy

2

提示

样例解释:这两对是(2,5)与(5,2)。
【数据范围】
对于50%的数据,1≤n≤2000。
对于接下来20%的数据,1≤ai≤100000。
对于100%的数据,1≤n≤1000000,1≤ai≤230,1≤X≤230。

我一拿到异或就很开心,因为异或的我已经做了好几道求和的了。

这题我的思路是map,然后查找,超时。

然后我还以为是什么高级算法,就放弃了。

赛后补题花絮:问了大佬以后是二分查找

我用stl(我只会stl!)超时,氧气优化也不行,快读c语言试了个遍,卡在(1000+)s

后来上网查了一下,stl慢,手打upper和lower

​​​​​​​

 

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long ll;
typedef double db;
const int maxn=1e5+5;
ll n,x;
ll a[1000005];
ll cnt;
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9')
    {
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9')
    {
        x=x*10+ch-48;
        ch=getchar();
    }
    return x*f;
}
void write(ll x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9)write(x / 10);
    putchar(x % 10 + '0');
}
int lowbou(ll a[],ll l,ll r,ll tar)
{
	while(l<=r){
		ll mid=(l+r)/2;
		if (a[mid]<tar) l=mid+1;
		else r=mid-1;
	}
	return l;
}
int uppbou(ll a[],ll l,ll r,ll tar)
{
	while(l<=r){
		ll mid=(l+r)/2;
		if (a[mid]<=tar) l=mid+1;
		else r=mid-1;
	}
	return l;
}
int main ()
{

    n=read();
    x=read();
    for(ll i=1; i<=n; i++)
    {
        a[i]=read();
    }
    sort(a+1,a+1+n);
    for(ll i=1; i<=n; i++)
    {
        ll sb=a[i]^x;
        cnt+=uppbou(a,1,n,sb)-lowbou(a,1,n,sb);

    }
write(cnt);

    return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值