Cod sursa(job #1562075)

Utilizator stoianmihailStoian Mihail stoianmihail Data 4 ianuarie 2016 19:39:47
Problema Frac Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 1.5 kb
#include <stdio.h>

#define Nadejde 20

#define ll long long

ll int N, K, M, count;
int size, div[Nadejde];

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

  int i;
  for (i = 3; i * i <= x; i += 2) {
    if (x % i == 0) {
      div[size++] = i;
      do {
        x /= i;
      } while (x % i == 0);
    }
  }
  if (x != 1) {
    div[size++] = x;
  }
}

/** Principiul includerii si al excluderii. **/
void bkt(int level, ll int x, int card) {
  if (x > M) {
    return;
  }
  if (level == size) {
    return;
  }

  /* Nu bagam in seama divizorul curent. */
  bkt(level + 1, x, card);

  /* Il bagam in seama. */
  card++;
  x = (ll)x * div[level];

  if (card & 1) {
    count += M / x;
  } else {
    count -= M / x;
  }
  bkt(level + 1, x, card);
}

/** Probeaza valorea "M". **/
ll int try() {
  count = 0;
  bkt(0, 1, 0);
  return M - count;
}

/** Cauta binar a "K"-a fractie. **/
ll int bSearch(ll int lo, ll int hi) {
  while (hi - lo > 1) {
    M = (lo + hi) >> 1;
    if (try() >= K) {
      hi = M;
    } else {
      lo = M;
    }
  }
  return hi;
}

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

  /* Citirea datelor. */
  fscanf(f, "%lld %lld", &N, &K);
  fclose(f);

  /* Da-mi divizorii lui "N". */
  getDiv(N);

  /* Calcularea solutiei si afisarea ei. */
  freopen("frac.out", "w", stdout);
  fprintf(stdout, "%lld\n", bSearch(0, ((ll)1LL << 61) + 1));
  fclose(stdout);

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