Cod sursa(job #1595792)

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

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

int n;
long long m = 1;
bool *primes;
vector<int> num;

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 ( vector<int>::iterator p = num.begin(); p != num.end() && *p <= 1 + sqrt(k);
        ++p){
        int l = *p;
        if ( k % l  ) continue;

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

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

void scriere(){
    out << m;
}

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