[Nowcoder 218399] Pares de números LY de G pequeña

Pares LY de G pequeña

Enlace del título: nowcoder 218399

Para Niu Ke:

——> Haz clic en mí para saltar <——

Idea general

Hay dos matrices y debe elegir un número cada una para que el valor de su OR exclusivo sea exactamente dos bits de 1 en el sistema binario.
Pregunte cuántas opciones tiene.

Ideas

Vemos XOR, considere el procesamiento a partir del número de bits.

Al ver que siempre que los dos sean diferentes, podemos considerar este método (¿similar a la mitad?).
Los números obtenidos invirtiendo los números en ambos lados para cada bit coinciden entre sí, y vea cuántos son iguales y están en ambos lados.
Esa coincidencia directa es la misma, podemos usar una tabla hash para lograrlo.

Entonces encontraremos un problema, es decir, las posiciones de los dos números pueden ser las mismas, y luego son las mismas, entonces no se puede contar, pero contaremos.
Luego consideramos la tolerancia y restamos esta situación.
Debido a que la negación es la misma, entonces negación significa que no hay negación. Entonces solo necesitamos encontrar cuántos pares son iguales en ambos lados y restar este número de la respuesta × 30 \ times 30× . 3 0 a.
Multiplicar30 303 0 porque todos pueden Por lo tanto, cada par tiene que restar treinta veces.

Entonces esta bien.

Código

#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;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43346722/article/details/114853824
Recomendado
Clasificación