Medio · Bits

Contar los bits 1

¿Cuántos bits 1 tiene la forma binaria de un número? Se llama popcount, y es una instrucción real de CPU.

En una fraseCuenta los bits a 1 desplazando n a la derecha y sumando n & 1; o borra un bit por paso con n &= n - 1, que itera exactamente tantas veces como unos haya.

El problema

Entrada: Un entero no negativo (0 <= n <= 1000000).

Salida: El número de bits 1 en n.

Ejemplo:

EntradaSalida
73

Tu solución

main.cpp — tu solución
Entrada personalizada para «Ejecutar mi entrada»

La corrección corre en tu navegador contra pruebas ocultas. Un bucle infinito se corta a los 3 segundos — aun así, asegúrate de que todo bucle tenga salida. Tu código se guarda solo mientras escribes.

¿Atascado? Pistas

Pista 1 — Suma los restos

Mientras n > 0: ones += n % 2; n /= 2;.

Pista 2 — El truco de Kernighan

while (n) { n &= n - 1; ones++; } limpia el 1 más bajo cada vuelta.

Solución (¡inténtalo primero!)
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int ones = 0;
    while (n > 0) {
        ones += n % 2;
        n /= 2;
    }
    cout << ones << endl;
    return 0;
}

C++ moderno tiene std::popcount(n) (C++20), que compila a una instrucción.

Análisis profundo

Por qué funciona

Tres formas de contar bits encendidos —desplazar y probar, el n&(n-1) de Kernighan y el popcount del hardware— son un recorrido compacto por «misma respuesta, tres perfiles de coste».

El coste

Ingenua: siempre 32 vueltas. Kernighan: una por bit encendido. Hardware: O(1) con una sola instrucción.

Dónde falla

  • Desplazar a la derecha un negativo con signo es comportamiento definido por la implementación y puede no terminar nunca, porque el bit de signo se rellena solo.
  • n >>= 1 sobre un negativo no llega jamás a cero. Usa unsigned.

Siguiente paso

Pon esos bits a trabajar: Representación binaria.

Dos cosas para recordar

  • Kernighan: una vuelta por bit encendido, no por bit.
  • Desplaza solo valores sin signo: el desplazamiento con signo está definido por la implementación.
🐞 Esta versión falla: ábrela y pruébala

Solo mira los 8 bits bajos

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int c = 0;
    for (int i = 0; i < 8; i++) {
        if (n % 2 == 1) c++;
        n /= 2;
    }
    cout << c << endl;
    return 0;
}