Cod sursa(job #2577)

Utilizator sandyxpSanduleac Dan sandyxp Data 17 decembrie 2006 19:57:29
Problema Fractii Scor 0
Compilator c Status done
Runda Arhiva de probleme Marime 1.81 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INFILE "fractii.in"
#define OUTFILE "fractii.out"
#define ll long long

int main() {
  freopen(INFILE, "r", stdin);
  freopen(OUTFILE, "w", stdout);
  ll i,j,e, n;
  scanf("%lld", &n);
  ll phi[1000000];
  memset(phi,0,sizeof(phi));
  long prime[8000], p=0;
  ll poww=1,x, divizor, totient_multiplier;

  //generate nr prime pana la sqrt(n) 
  //long* prim = (long *)malloc(sizeof(long)*(n+2)/*31701*/);
  /*memset(prim,0,sizeof(prim));
  prime[0]=0;

  for (i=2;i <= n;i++)
    for (j=i; j*i <= n;j++)
      prim[i*j] = 1;
  for (i=2;i*i<n;i++) if (!prim[i]) prime[++prime[0]] = i;*/
  
  char prim[ n/8/2 + 5 ];memset(prim,0,sizeof(prim));
  prime[0]=1;prime[1]=2;
  
  for (i=1; (i*i<<1)+(i<<1) <= n; i++) 
    if ( ( prim[ i>>3 ] & (1 << (i&7)) ) == 0) 
      for (j=(i*i<<1) + (i<<1); (j<<1|1) <= n;
          j+= (i<<1|1) )
        prim[ j>>3 ] |= (1 << (i&7));
  for (i=1; (i<<1|1)<=n; i++)
     if ((prim[ i>>3 ] & (1 << (i&7))) == 0)
       prime[++prime[0]] = (i<<1|1);
  
  //numere prime si puterile lor..
  for (i=1;i<=prime[0];i++) {
    poww=prime[i];
    for (e=1;poww <= n;e++) 
      phi[poww] = (prime[i]-1)*poww/prime[i], poww*=prime[i];
      // totient (p^e) = (p - 1) * p^(e - 1)
  }
  
  for (i=2;i<=n;i++) 
    if (!phi[i]) {
      //printf("%ld\n",i);
     if (prim[i] == 0) phi[i]=i-1; else
     {
      phi[i]=1;//tot caut div primi ...
      x=i;divizor=1;
      do {
        totient_multiplier = 1;
        while (x>1 && x%prime[divizor]==0) 
          x/=prime[divizor],totient_multiplier*=prime[divizor];

        if (totient_multiplier>1) {
          phi[i]*=phi[totient_multiplier] * phi[x]; break;}
        divizor++;
      } while (x>1);
     }
    }
  ll sum=0;
  for (i=2;i<=n;i++) sum += phi[i]; 
  sum*=2;sum+=1;
  printf("%lld", sum);
  return 0;
}