M-选数异或_第五届太原理工大学程序设计竞赛新生赛(同步赛) (nowcoder.com)
题目描述
给定一个长度为 nnn 且下标从 1 开始的数组 aaa ,请计算有多少个数对 (i,j)(i,j)(i,j) 满足 i<ji \lt ji<j 且 ai xor aj>0a_i\ xor\ a_j >0ai xor aj>0
xor(按位异或)运算符 (`^`) 将其第一操作数的每个位与其第二操作数的相应位进行比较。 如果其中一个操作数中的位为 0,而另一个操作数中的位为 1,则相应的结果位设置为 1。 否则,将对应的结果位设置为 0。
0110 XOR 1100 = 1010
输入描述:
第一行一个正整数 n (1≤n≤106)n\,( 1 \le n\le10^6)n(1≤n≤106) ,表示数组 aaa 的长度。 第二行输入 nnn 个整数,第 iii 个整数表示 ai (0≤ai≤106)a_i\,(0\le a_i\le 10^6)ai(0≤ai≤106) 。
输出描述:
输出一行一个整数,代表答案。
示例1
输入
3
6 0 12
输出
3
说明
6 xor 0 = 6,6 xor 12 = 10,0 xor 12 = 12,因此三个数对 (1,2) (1,3) (2,3) 都符合条件。
示例2
输入
4
1 1 2 3
输出
5
说明
有五个数对符合条件:(1,3) (1,4) (2,3) (2,4) (3,4)
CV代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(long long i=a;i<=n;i++)
#define per(i,a,n) for(long long i=n;i>=n;i--)
typedef long long ll;
const int MAXN = 1e6+7;
ll hash1[MAXN];
ll val;
set<int> st;
int main()
{
ll n;cin>>n;
ll sum = n*(n-1)/2;
while(n--)
{
cin>>val;
hash1[val]++;
st.insert(val);
}
ll cnt = 0;
for(auto i:st){
cnt += hash1[i]*(hash1[i]-1)/2;
}
cout<<sum-cnt;
return 0;
}
关键点:
0、思路:
排列组合问题,满足题意数=C(n,2) - C(m,2)
m:自己异或自己不满足题意,但是每个数字都可能出现自己异或自己的情况,所以要求和
1、hash是c++模板库关键字
2、利用set容器特点减少遍历次数
3、异或的运用:
3.1、a^=b^=a^=b 不另开空间原地交换a和b的值;