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