Cod sursa(job #3367037)

Utilizator Emre12Isleam Emre Emre12 Data 5 octombrie 2026 22:35:18
Problema Numere 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.38 kb
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <stack>

#define MAXDIGIT 600
#define BAZA ((long long)(1ULL << 32))
#define BAZAPRINT (unsigned int)(1e9)

struct nrMare {
  unsigned int dig[MAXDIGIT / 8];
  int nrD;
  void setStr(const std::string &a) { // citeste un nr direct dintr'un string
    clear();
    int i = 0;
    for (i = 0; i < a.size(); i++) {
      multiplyInt(10);
      addInt(a[i] - '0');
    }
  }
  void print(FILE *fout) { // printeaza nr in fout
    nrMare aux;
    aux.copy(*this); // auxiliar ca sa nu fie distructiva functia si pur
    //  simplu sa printeze
    std::stack<int> rez; // stiva temporara sa tin digitele in minte
    if (nrD == 0) {
      fprintf(fout, "0");
      return;
    }
    while (nrD)
      rez.push(divide(BAZAPRINT));
    fprintf(fout, "%d", rez.top());
    rez.pop();
    while (!rez.empty()) {
      fprintf(fout, "%09d", rez.top());
      rez.pop();
    }
    this->copy(aux);
  }
  void multiplyInt(unsigned long long b) {
    if (b == 0) {
      clear();
      return;
    }
    int i;
    unsigned long long t = i = 0;
    while (i < nrD || t > 0) {
      t += (unsigned long long)b * (unsigned long long)dig[i];
      dig[i] = (unsigned int)t;
      t = t >> 32;
      ++i;
    }
    nrD = std::max(i, nrD);
  }
  void multiplyHuge(nrMare b) {
    int i, pBase = 0;
    nrMare aux, rez;
    i = 0;
    rez.clear();
    while (i < b.nrD) {
      aux.copy(*this);
      aux.multiplyInt((unsigned long long)b.dig[i]);
      if (b.dig[i]) {
        memmove(aux.dig + pBase, aux.dig, sizeof(aux.dig[0]) * aux.nrD);
        memset(aux.dig, 0, sizeof(aux.dig[0]) * pBase);
        aux.nrD += pBase;
      }
      pBase++;
      rez.add(aux);
      ++i;
    }
    copy(rez);
  }
  int divide(int a) {
    unsigned long long t = 0;
    for (int i = nrD - 1; i >= 0; i--) {
      t = t * BAZA + dig[i];
      dig[i] = t / a;
      t %= a;
    }
    while (nrD > 0 && dig[nrD - 1] == 0)
      nrD--;
    return t; // returneaza modulul
  }
  void add(const nrMare &a) {
    int i;
    unsigned long long t = i = 0;
    while (i < nrD || i < a.nrD || t > 0) {
      t += (unsigned long long)a.dig[i] + (unsigned long long)dig[i];
      dig[i] = (unsigned int)t;
      t = t >> 32;
      ++i;
    }
    nrD = std::max(i, nrD);
    nrD = std::max(a.nrD, nrD);
  }
  void addInt(unsigned int a) {
    int i;
    unsigned long long t = i = 0;
    t = a;
    while (i < nrD || t) {
      t += dig[i];
      dig[i] = (unsigned int)t;
      t = t >> 32;
      ++i;
    }
    nrD = std::max(i, nrD);
  }
  inline void clear() {
    memset(dig, 0, sizeof(dig[0]) * (MAXDIGIT / 8));
    nrD = 0;
  }
  void set(int a) {
    clear();
    dig[0] = a;
    nrD = 1;
  }
  // baga a in nr mare curent (operatorul = )
  void copy(const nrMare &a) {
    clear();
    for (int i = 0; i < a.nrD; i++)
      dig[i] = a.dig[i];
    nrD = a.nrD;
  }
  int cmp(const nrMare &a) const {
    if (nrD != a.nrD)
      return nrD < a.nrD ? -1 : 1;
    for (int i = nrD - 1; i >= 0; i--)
      if (dig[i] != a.dig[i])
        return dig[i] < a.dig[i] ? -1 : 1;
    return 0;
  }
  void setBit(int b) {
    int i = b / 32;
    dig[i] |= 1ULL << b % 32;
    if (i >= nrD)
      nrD = i + 1;
  }
  void clearBit(int b) {
    int i = b / 32;
    dig[i] ^= 1ULL << b % 32;
    while (nrD > 0 && dig[nrD - 1] == 0)
      nrD--;
  }
};
nrMare powHuge(const nrMare &base, int exp) {
  nrMare rez, cur;
  rez.set(1);
  cur.copy(base);
  while (exp) {
    if (exp % 2)
      rez.multiplyHuge(cur);
    exp /= 2;
    if (exp)
      cur.multiplyHuge(cur);
  }
  return rez;
}
bool checkRoot(const nrMare &p, int k,
               nrMare &a) { // exista a^k = p? daca da pune l in a
  int nrBitsP = ((p.nrD - 1) * 32) + (32 - __builtin_clz(p.dig[p.nrD - 1]));
  int bitBound = (nrBitsP + k - 1) / k;
  nrMare r, pow;
  r.clear();
  int c;
  for (int i = bitBound - 1; i >= 0; i--) {
    r.setBit(i);
    pow = powHuge(r, k);
    c = p.cmp(pow);
    if (c == 0) {
      a.copy(r);
      return 1;
    }
    if (c == -1)
      r.clearBit(i);
  }
  return 0;
}
nrMare p, a;
int main() {
  FILE *fout;
  std::ifstream fin("numere2.in");
  fout = fopen("numere2.out", "w");

  std::string str;
  fin >> str;
  p.setStr(str);
  int k;
  a.clear();
  for (k = 333; k >= 2; k--) {
    if (checkRoot(p, k, a)) {
      a.print(fout);
      fprintf(fout, "\n%d", k);
      return 0;
    }
  }
  p.print(fout);
  fprintf(fout, "\n1");
  return 0;
}