Cod sursa(job #2576)

Utilizator sandyxpSanduleac Dan sandyxp Data 17 decembrie 2006 19:56:48
Problema Fractii Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.97 kb
#include<iostream>
#include<vector>
#include<cmath>
#define INFILE "fractii.in"
#define OUTFILE "fractii.out"
typedef long long ll;
using namespace std;

int main() {
  freopen(INFILE, "r", stdin);
  freopen(OUTFILE, "w", stdout);
  ll i, j, e, n;
  scanf("%lld", &n);
  vector<ll> phi(1000001);
  //memset(phi,0,sizeof(phi));
  long prime[10000], 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;*/
  
  int N = (int)sqrt(n);
  char prim[ N/8/2 + 5 ];memset(prim,0,sizeof(prim));
  prime[0]=1;prime[1]=2;
  cerr << "kkt" << endl;
  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 << (j&7));
  for (i=1; (i<<1)+1<=N; i++)
     if ((prim[ i>>3 ] & (1 << (i&7))) == 0)
       prime[++prime[0]] = (i<<1)+1;
  
  for (i=1; i<=prime[0]; i++) cerr << prime[i] << ", ";
  cerr << endl;

  //numere prime si puterile lor..
  for (i=1;i<=prime[0];i++) {
    poww=prime[i];
    for (e=1;poww <= n/prime[i];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;
}