Cod sursa(job #1562034)

Utilizator stoianmihailStoian Mihail stoianmihail Data 4 ianuarie 2016 19:07:25
Problema Pairs Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 1.96 kb
#include <stdio.h>

#define MAX_VAL 1000000
#define MAX_P 78500
#define LIMIT 1000
#define Nadejde 8

#define ll long long

int N;
int low[MAX_VAL + 1];   // low[i] = cel mai mic numar prim care il divide pe i.
int freq[MAX_VAL + 1];  // freq[i] = de cate ori apare "i" ca divizor.
int size, div[Nadejde];

/** Ciurul lui Eratostene. **/
void sieve() {
  int i, j, step;

  low[2] = 2;
  for (i = 3; i < LIMIT; i += 2) {
    if (!low[i]) {
      low[i] = i;
      for (step = (i << 1), j = i * i; j <= MAX_VAL; j += step) {
        if (!low[j]) {
          low[j] = i;
        }
      }
    }
  }
  for (; i < MAX_VAL; i += 2) {
    if (!low[i]) {
      low[i] = i;
    }
  }
}

/** Obtine divizorii lui "x". **/
void getDiv(int x) {
  int curr;
  
  size = 0;
  if (x % 2 == 0) {
    div[size++] = 2;
    x /= (x & -x);
  }
  while (x > 1) {
    div[size++] = (curr = low[x]);
    do {
      x /= curr;
    } while (curr == low[x]);
  }
}

/** Principiul includerii si al excluderii. **/
void bkt(int level, ll int x, int card) {
  if (level == size) {
    return;
  }
  /* Nu bagam in seama divizorul curent. */
  bkt(level + 1, x, card);

  /* Il bagam in seama. */
  card++;
  x = x * div[level];
  
  if (card & 1) {
    freq[x]++;
  } else {
    freq[x]--;
  }
  bkt(level + 1, x, card);
}

int main(void) {
  int i, val;
  FILE *f = fopen("pairs.in", "r");

  sieve();

  /* Citirea datelor. */
  fscanf(f, "%d", &N);
  for (i = 0; i < N; i++) {
    fscanf(f, "%d", &val);
    getDiv(val);
    bkt(0, 1, 0);
  }
  fclose(f);

  /* Calcularea solutiei. */
  ll int count = 0;
  for (i = 2; i <= MAX_VAL; i++) {
    if (freq[i] > 0) {
      count += ((ll)freq[i] * (freq[i] - 1)) / 2;
    } else if (freq[i] < 0) {
      count -= ((ll)-freq[i] * (-freq[i] - 1)) / 2;
    }
  }
  count = (((ll)N * (N - 1)) / 2) - count;

  /* Afisarea solutiei. */
  freopen("pairs.out", "w", stdout);
  fprintf(stdout, "%lld\n", count);
  fclose(stdout);

  /// Multumim Doamne!
  puts("Doamne ajuta!");
  return 0;
}