Pagini recente » Borderou de evaluare (job #3135754) | Borderou de evaluare (job #3367039) | Borderou de evaluare (job #3367037) | Monitorul de evaluare | Cod sursa (job #3367039)
#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;
}