[Nowcoder 218399] LY number pairs of small G

LY pairs of small G

Title link: nowcoder 218399

To Niu Ke:

——>Click me to jump<——

General idea

There are two arrays, and you need to choose one number each so that the value of their exclusive OR is exactly two bits of 1 in the binary system.
Ask how many options do you have.

Ideas

We see XOR, consider processing from the number of bits.

Seeing that as long as the two are different, we can consider this method (similar to halving?).
The numbers obtained by inverting the numbers on both sides for each bit match each other, and see how many are the same and are on both sides.
That direct match is the same, we can use a hash table to achieve.

Then we will find a problem, that is, the positions of the two numbers may be the same, and then they are the same, then it cannot be counted, but we will count.
Then we consider tolerance and subtract this situation.
Because the negation is the same, then negation means no negation. Then we only need to find how many pairs are the same on both sides, and subtract this number from the answer × 30 \times 30× . 3 0 to.
To multiply30 303 0 because every one can Thus, each pair has to subtract thirty times.

Then it's fine.

Code

#include<cstdio>
#include<cstring>
#define mo 1000007
#define ll long long

using namespace std;

struct Hash {
    
    
	int x, to, nxt;
}e[3000007];
int le[3000007], KK;
ll n, m, a[500001], b[500001];
ll ans;

void Hash_push(int now) {
    
    //哈希操作
	ll pl = now % mo;
	for (int i = le[pl]; i; i = e[i].nxt)
		if (e[i].to == now) {
    
    
			e[i].x++;
			return ;
		}
	e[++KK] = (Hash){
    
    1, now, le[pl]}; le[pl] = KK;
}

ll Hash_ask(ll now) {
    
    
	ll pl = now % mo;
	for (int i = le[pl]; i; i = e[i].nxt)
		if (e[i].to == now) return e[i].x;
	return 0;
}

int main() {
    
    
	scanf("%lld %lld", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for (int i = 1; i <= m; i++) scanf("%lld", &b[i]);
	
	for (int i = 1; i <= n; i++)
		for (int j = 0; j < 30; j++)
			Hash_push(a[i] ^ (1 << j));//插入一边异或一个位置
	
	for (int i = 1; i <= m; i++)
		for (int j = 0; j < 30; j++)
			ans += 1ll * Hash_ask(b[i] ^ (1 << j));//寻找另一边也异或一个位置和是否有前面一边异或一个位置一样的
	
	memset(le, 0, sizeof(le));//去掉异或的位置是同一个位置的情况
	memset(e, 0, sizeof(e));
	KK = 0;
	for (int j = 1; j <= n; j++)
		Hash_push(a[j]);
	for (int j = 1; j <= m; j++)
		ans -= Hash_ask(b[j]) * 30ll;
	
	printf("%lld", ans >> 1);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/114853824