Cod sursa(job #1595684)

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

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

int n, m;
bool *primes;

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

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 = 0; 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]) continue;
        for(int j = i; j <= n / i; j++){
            primes[j * i] = false;
        }
    }

    for(int i = 1; i <= n; i++){
        m += phi(i);
    }
}

void scriere(){
    out << m;
}

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