Cod sursa(job #1595701)

Utilizator garovatGarovat Adrian garovat Data 10 februarie 2016 14:49:38
Problema Fractii Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.41 kb
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;

ifstream in("fractii.in");
ofstream out("fractii.out");

int n, m = 1;
bool *primes;

void citire(){
    in >> n;
    primes = new bool[n + 1];
    fill_n(primes, n + 1, true);
}

int binary_gcd(int u, int v){
    int shift;

    if (u == 0) return v;
    if (v == 0) return u;

    for (shift = 0; ((u | v) & 1) == 0; ++shift) {
        u >>= 1;
        v >>= 1;
    }

    while ((u & 1) == 0)
        u >>= 1;

    do {
        while ((v & 1) == 0)
            v >>= 1;
        if (u > v) { int t = v; v = u; u = t;}
        v = v - u;
    } while (v != 0);

    return u << shift;
}

int phi(int k){
    if ( n < 2 )
        return 1;

    if ( primes[k] )
        return k-1;

    if ( (k & 1) == 0 ){
        int m = k >> 1;
        return !(m & 1) ? phi(m)<<1 : phi(m);
    }

    for ( int p = 2; p <= n; p++){
        if (!primes[p]) continue;
        if ( n % p  ) continue;

        int o = n/p;
        int d = binary_gcd(p, o);
        return d==1? phi(p)*phi(o) : phi(p)*phi(o)*d/phi(d);
    }
}

void rezolvare(){
    for(int i = 2; i <= sqrt(n); i++){
        if(primes[i])
            for(int j = i; j <= n / i; j++){
                primes[j * i] = false;
            }
    }
    for(int i = 2; i <= n; i++){
        m += 2 * phi(i);
    }
}

void scriere(){
    out << m;
}

int main()
{
    citire();
    rezolvare();
    scriere();
    return 0;
}