Cod sursa(job #2355139)

Utilizator TomKodeColev Thomas-Daniel TomKode Data 25 februarie 2019 20:52:56
Problema Fractii Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.1 kb
#include <fstream>
#include <cmath>
#define SIZE 1000000
#define ALLOCATED SIZE+10
using namespace std;

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

short prime[ALLOCATED], phiCalculated[ALLOCATED];
int phi[ALLOCATED];

int main() {
    int n, i;
    long long sphi;

    cin >> n;
    for (i = 1; i <= n; i++)
    {
        phiCalculated[i] = 0;
    }
    prime[1] = 0;
    prime[2] = 1;
    //numerele pare altele decat 2 nu sunt prime
    for (i = 4; i <= n; i+=2) {
        prime[i] = 0;
    }
    //numerele impare ar putea fi prime
    for (i = 3; i <= n; i+=2)
    {
        prime[i] = 1;
    }
    //aplicam ciurul lui Eratostene peste numerele impare
    int l = sqrt(n);
    for (i = 3; i <= l; i+=2) {
        if (prime[i]) {
            for (int j = 2 * i; j <= n; j+=i) {
                prime[j] = 0;
            }
        }
    }

    phi[1] = 0;

    for (i=2; i<=n; i++) {
        if (prime[i]) {
            //phi(n) = n-1 daca n este prim
            phi[i] = i - 1;
            phiCalculated[i] = 1;
            //si pentru puterile numarului prim avem formula
            for (long long j = i; j*i <= n; j*=i) {
                phi[i*j] = j * phi[i];
                phiCalculated[i*j] = 1;
            }
        } else {
            if (!phiCalculated[i]) {
                // pentru numerele compuse folosim cealalta formula
                int d = 2;
                //gasim cel mai mic divizor prim al numarului
                while (i%d) {
                    d++;
                }
                int a, b = i;
                //pe care il extragem la maxim
                while (b%d==0) {
                    b /= d;
                }
                a = i / b;
                //avem garantia ca a si b vor fi prime intre ele conform acestei strategii
                phi[i] = phi[a] * phi[b];
                phiCalculated[i] = 1;
            }
        }
    }

    sphi = 0;
    for (i = 2; i <= n; i++)
    {
        sphi += phi[i];
    }

    cout << 2 * sphi + 1;

    cin.close();
    cout.close();
    return 0;
}