Cod sursa(job #1554688)

Utilizator felix_vsGherasim Felix felix_vs Data 21 decembrie 2015 16:48:05
Problema Fractii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.53 kb
#include <cctype>

#include <fstream>
#include <vector>

static auto get_smallest_prime_divisors(int n) -> std::vector<int> {
  auto smallest_prime_divisors = std::vector<int>(n + 1, 0);

  smallest_prime_divisors[1] = 1; // just... ok...

  for (auto i = 2; i < n; ++i) {
    if (smallest_prime_divisors[i] != 0)
      continue;

    for (auto j = i; j < n; j += i) {
      if (smallest_prime_divisors[j] == 0)
        smallest_prime_divisors[j] = i;
    }
  }

  return smallest_prime_divisors;
}

static auto compute_eulers_phi(std::vector<int> const &smallest_prime_divisors,
                               int n) -> int {
  auto phi = 1;
  while (n != 1) {

    auto divisor = smallest_prime_divisors[n];
    n /= smallest_prime_divisors[n];
    // pi ^ (ki -1)
    auto p_pow_k = 1;

    while (smallest_prime_divisors[n] == divisor) {
      n /= smallest_prime_divisors[n];
      p_pow_k *= divisor;
    }
    phi *= (divisor - 1) * p_pow_k;
  }
  return phi;
}

static auto get_num_irreductible_fractions(int n) -> std::int64_t {
  auto const smallest_prime_divisors = get_smallest_prime_divisors(n + 1);

  auto num = std::int64_t{};

  for (auto i = 2; i <= n; ++i) {
    num += compute_eulers_phi(smallest_prime_divisors, i);
  }

  // count 1/1 once
  num = 2 * num + 1;

  return num;
}

auto main() -> int {
  std::ifstream fin{"fractii.in"};
  auto n = int{};
  fin >> n;
  fin.close();

  std::ofstream fout{"fractii.out"};
  fout << get_num_irreductible_fractions(n);

  return 0;
}