Cod sursa(job #188895)

Utilizator anna_bozianuBozianu Ana anna_bozianu Data 10 mai 2008 18:10:00
Problema Fractii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.47 kb
#include<stdio.h>   
unsigned long long phi[1000001],i,j,k,sol,n;
int main()
{   
    freopen("fractii.in","rt",stdin);
    freopen("fractii.out","wt",stdout);
    scanf("%llu",&n);
    phi[1]=1;sol=1;
    for(i=2;i<=n;i++)
    { if(!phi[i])
      { phi[i]=i-1;
        for(j=i*i;j<=n;j+=i)
        { if(phi[j])continue;
          phi[j]=i;
        }
      }
      else
      { j=phi[i]; phi[i]=j-1; k=i/j;
        while(k%j==0){phi[i]*=j;k/=j;}
        phi[i]*=phi[k];
      }
      sol+=2*phi[i];
     }
     printf("%llu",sol);
     return 0;
}
// phi[i]=indicatorul lui euler al numarului i
// phi[i]=numarul de numere mai mici decat i si prime cu i
// phi[i]=numarul de fractii ireductibile j/i cu j<i
//       =numarul de fractii ireductibile i/j cu j<i
// sol=1+suma(2*phi[i])
// folosim phi[p]=p-1;pentru p=numar prim
// phi[p^k]=(p-1)*p^(k-1);pentru p=numar prim
// phi[m1*m2]=phi[m1]*phi[m2] daca m1,m2 prime intre ele
// se obtine urmatorul algoritm care utilizeaza ciurul lui eratostene
// formulele de mai sus si programare dinamica
// daca pt i de la 1 la n in phi[i] avem 0 atunci i este prim si facem
// phi[i]=i-1
// marcam apoi multiplii lui i pt care i este factorul prim minimal prin
// marcajul phi[i]=i
// daca in phi[i] avem p!=0 atunci p este cel mai mic factor prim pt i
// atunci putem scrie i=m1*m2 unde m=p^k si m2 nu contine p deci e prim cu m1
// aplicam acum formula pt phi[m1]=phi[p^k]
// si luam din spate valoarea lui phi[m2]