Cod sursa(job #1595780)

Utilizator garovatGarovat Adrian garovat Data 10 februarie 2016 15:36:39
Problema Fractii Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.52 kb
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;

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

int n;
long long 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 shl = 0;

  while ( u>0 && v>0 && u!=v ) {
    // even numbers?
    bool eu = (u & 1) == 0;
    bool ev = (v & 1) == 0;

    if ( eu && ev ) {
      ++shl;
      u /= 2;
      v /= 2;
    }
    else if ( eu && !ev ) u /= 2;
    else if ( !eu && ev ) v /= 2;
    else if ( u>=v ) u = (u-v)/2;
    else {
      int tmp = u;
      u = (v-u)/2;
      v = tmp;
    }
  }

  return u==0? v<<shl : u<<shl;
}

int phi(int k){
    if ( k == 1 )
        return 1;

    if ( k < 2 )
        return 0;

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

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

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

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

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;
}