Cod sursa(job #1727171)

Utilizator arenauserIon Ion arenauser Data 9 iulie 2016 23:12:57
Problema Fractii Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.71 kb
#include <fstream>
#include <vector>

//http://www.infoarena.ro/problema/fractii

const char* inFile = "fractii.in";
const char* outFile = "fractii.out";

std::vector<int> init_primes(int n)
{
    std::vector<bool> sieve (n + 1, true);

    auto max_prime_check = int(sqrt(n));

    for (int p = 2; p <= max_prime_check; ++p)
    {
        if (!sieve[p]) continue;

        auto multiple_p = 2 * p;

        while (multiple_p <= n)
        {
            sieve[multiple_p] = false;
            multiple_p += p;
        }
    }

    std::vector<int> primes;

    primes.reserve(int(sqrt(n) / 2));

    for (int i = 2; i <= n; ++i)
    {
        if (sieve[i])
        {
            primes.push_back(i);
        }
    }

    return primes;
}



int euler_totient(int k, const std::vector<int>& cached_primes)
{
    //totient = k * prod(1 - 1/p), for all p prime which divide k
    int prod_p_minus = 1;
    int prod_p = 1;
    for (auto p : cached_primes)
    {
        if (p > k) break;

        if (k % p == 0)
        {
            prod_p *= p;
            prod_p_minus *= (p - 1);
        }
    }

    return  (k / prod_p) * (prod_p_minus);
}

int compute_num_irred_fractions(int n)
{
    auto smaller_primes = init_primes(n);

    int result = 1;

    for (int i = 2; i <= n; ++i)
    {
        result += 2 * euler_totient(i, smaller_primes);
    }

    return result;
}


int main()
{
    int n = 0;
    {
        std::ifstream readFile(inFile);
        if (!readFile) return -1;

        readFile >> n;
    }

    int num = compute_num_irred_fractions(n);

    {
        std::ofstream writeFile(outFile);
        writeFile << num;
    }

    return 0;
}