AtCoder Beginner Contest 323 D

https://atcoder.jp/contests/abc323/tasks/abc323_d

1が5個あったとしたら、
(1 + 1) + (1 + 1) + 1 = (2 + 2) + 1 = 4 + 1
となるので、2個に集約できますね。これは5を二進法で表して101で、1の数をカウントしたものですね。
3が3個、6が1個なら、6は3+3なので、結局3が5個で、やっぱり2個に集約できます。

// Merge Slimes
#![allow(non_snake_case)]

use std::collections::HashMap;


//////////////////// library ////////////////////

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}

fn div_pow(mut n: i64, d: i64) -> (i64, i64) {
    let mut e = 0;
    while n % d == 0 {
        e += 1;
        n /= d
    }
    (e, n)
}

fn count_bits(mut n: i64) -> i64 {
    let mut e = 0;
    while n > 0 {
        e += n & 1;
        n >>= 1
    }
    e
}


//////////////////// process ////////////////////

fn read_input() -> Vec<(i64, i64)> {
    let N: usize = read();
    let slimes: Vec<(i64, i64)> = (0..N).map(|_| read_vec()).
                                            map(|v| (v[0], v[1])).collect();
    slimes
}

fn F(slimes: Vec<(i64, i64)>) -> i64 {
    let mut dic: HashMap<i64, i64> = HashMap::new();
    for (S, C) in slimes.into_iter() {
        let (e, n) = div_pow(S, 2);
        let entry = dic.entry(n).or_insert(0);
        *entry += C << e
    }
    dic.into_iter().map(|(_n, e)| count_bits(e)).sum::<i64>()
}

fn main() {
    let slimes = read_input();
    println!("{}", F(slimes))
}