Cod sursa(job #69699)

Utilizator cos_minBondane Cosmin cos_min Data 3 iulie 2007 22:54:12
Problema Fractii Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.51 kb
#include <stdio.h>
#include <vector>
using namespace std;

#define in "fractii.in"
#define out "fractii.out"

int N, j, r, Q;
int S[31], G[31], Pow[31]; 
bool ok[1000066];
int phi[1000066];
vector<int> V;

int Solve(int);

int main()
{
    freopen(in,"r",stdin);
    freopen(out,"w",stdout);
    
    scanf("%d", &N);
    
    for ( int i = 1; i <= N; ++i )
        ok[i] = 0, phi[i] = 0;
    
    for ( int i = 2; i <= N/2; ++i )
    {
        j = 2;
        while ( i*j <= N )
        {
              ok[i*j] = 1;
              j++; 
        }
    } 
    
    phi[1] = 1;
    for ( int i = 2; i <= N; ++i )
        if ( ok[i] == 0 )
        {
             phi[i] = i-1;
             V.push_back(i);
        }
    
    long long K, P, T, W;
    
    for ( int i = 0; i < V.size(); ++i )
    {
        K = V[i];
        P = K*K;
        for ( ; N-P >= 0 ; )
        {
            for ( int a = 1; a*P <= N && a < P; ++a )
            {
                if ( phi[a] == 0 ) phi[a] = Solve(a); 
                
                if ( phi[a] != 0 ) 
                {
                     phi[P*a] = (V[i]-1)*K*phi[a];
                }
            }
            K = P;
            P *= V[i];
        }
    }
    
    for ( int a = 2; a <= N; ++a )
    {
        if ( phi[a] == 0 ) phi[a] = Solve(a); 
        if ( phi[a] != 0 )
        {
             T = a, W = 1;
             while ( 0 <= N - T )
             {
                   phi[T] = phi[a]*W;
                   W = T;
                   T *= a;
             } 
        }
    }
        
    
    long long total=0;

    for ( int i = 1; i <= N; ++i )
    {
        //if ( ok[i] == 1 && phi[i] == 0 ) phi[i] = Solve(i);
        total += phi[i];
    } 
        
    printf("%lld", 2*(total-1)+1); // phi[1] = 1
}

int Solve(int t)
{
    r = 0, Q = t;
    int C, b;
    
    for ( int i = 0; V[i]*V[i] <= Q && t > 1 && i < V.size(); ++i )
    {
        Pow[i+1] = 0;
        b = t;
        C = 1;
        if ( t % V[i] == 0 ) r+=1, S[r] = V[i]-1, G[r] = V[i];
        while ( t % V[i] == 0 ) t /= V[i], b /= V[i], C *=(V[i]-1) ;
    /*
        if ( phi[b] != 0 && b < C )
        {
             C /= (V[i]-1);
             Q = C*phi[b];
             return Q; 
        }*/
    }
    
    if ( t > 1 ) r+=1, S[r] = t-1, G[r] = t;
    
    for ( int i = 1; i <= r; ++i )
    {
        Q /= G[i];
    }
    
    for ( int i = 1; i <= r; ++i )
    {
        Q *= S[i];
    }
    
    return Q;
}