Cod sursa(job #3141458)

Utilizator cdenisCovei Denis cdenis Data 14 iulie 2023 01:33:32
Problema Numere 2 Scor 45
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 9.19 kb
#include <fstream>
#include <iostream>
#include <cstring>
#include <forward_list>

using namespace std;

#define MAX_LEN 200

class bigint {
private:
    char num[MAX_LEN];
    size_t len;
    bool sign;
public:
    bigint(int val = 0);
    bigint(const char *);
    bigint(const bigint &);
    ~bigint();

    size_t get_length() const;

    friend bigint abs(const bigint &);

    // operator de atribuire
    bigint &operator=(const bigint &);

    // operator de indexare
    int operator[](const size_t) const;

    // operatori de incrementare si decrementare
    bigint &operator++();			// forma prefixata
    bigint operator++(int fictiv);	// forma postfixata
    bigint &operator--();			// forma prefixata
    bigint operator--(int fictiv);	// forma postfixata

    // operatori aritmetici
    friend bigint operator-(const bigint &);
    friend bigint operator+(const bigint &, const bigint &);
    friend bigint operator-(const bigint &, const bigint &);
    friend bigint operator*(const bigint &, const bigint &);
    friend bigint operator/(const bigint &, const bigint &);
    friend bigint operator%(const bigint &, const bigint &);

    // operatori de atribuire compusi
    bigint &operator+=(const bigint &);
    bigint &operator-=(const bigint &);
    bigint &operator*=(const bigint &);
    bigint &operator/=(const bigint &);
    bigint &operator%=(const bigint &);

    // operatori de egalitate
    friend bool operator==(const bigint &, const bigint &);
    friend bool operator!=(const bigint &, const bigint &);

    // operatori relationali
    friend bool operator<(const bigint &, const bigint &);
    friend bool operator<=(const bigint &, const bigint &);
    friend bool operator>(const bigint &, const bigint &);
    friend bool operator>=(const bigint &, const bigint &);

    // operatori de citire si scriere
    friend istream &operator>>(istream &, bigint &);
    friend ostream &operator<<(ostream &, const bigint &);
};

bigint::bigint(int val)
{
    if (val < 0) {
        sign = 1;
        val = -val;
    } else {
        sign = 0;
    }

    len = 0;

    do {
        num[len++] = val % 10;
        val /= 10;
    } while (val);

    num[len] = 0;
}

bigint::bigint(const char *s)
{
    if (s[0] == '-') {
        sign = 1;
        len = strlen(s + 1);
        for (size_t i = 1; i <= len; i++) {
            num[len - i] = s[i] - '0';
        }
    } else {
        sign = 0;
        len = strlen(s);
        for (size_t i = 0; i < len; i++) {
            num[len - i - 1] = s[i] - '0';
        }
    }
    num[len] = 0;
}

bigint::bigint(const bigint &obj)
{
    sign = obj.sign;
    len = obj.len;
    memcpy(num, obj.num, len + 1);
}

bigint::~bigint()
{
    sign = 0;
    len = 0;
    num[0] = 0;
}

size_t bigint::get_length() const
{
    return len;
}

bigint abs(const bigint &obj)
{
    bigint tmp = obj;
    tmp.sign = 0;
    return tmp;
}

// operator de atribuire
bigint &bigint::operator=(const bigint &obj)
{
    sign = obj.sign;
    len = obj.len;
    memcpy(num, obj.num, len + 1);
    return *this;
}

// operator de indexare
int bigint::operator[](const size_t idx) const
{
    return num[len - idx - 1];
}

// operatori de incrementare si decrementare
bigint &bigint::operator++() // forma prefixata
{
    *this = (*this) + 1;
    return *this;
}

bigint bigint::operator++(int fictiv) // forma postfixata
{
    bigint tmp = *this;
    *this = (*this) + 1;
    return tmp;
}

bigint &bigint::operator--() // forma prefixata
{
    *this = (*this) - 1;
    return *this;
}

bigint bigint::operator--(int fictiv) // forma postfixata
{
    bigint tmp = *this;
    *this = (*this) - 1;
    return tmp;
}

// operatori aritmetici
bigint operator-(const bigint &obj)
{
    bigint tmp = obj;
    tmp.sign = !tmp.sign;
    return tmp;
}

bigint operator+(const bigint &obj1, const bigint &obj2)
{
    bigint tmp;
    char res, carry = 0;

    if (obj1.sign == obj2.sign) {
        size_t max_len = (obj1.len > obj2.len ? obj1.len : obj2.len);

        for (size_t i = 0; i < max_len; i++) {
            res = carry;

            if (i < obj1.len) {
                res += obj1.num[i];
            }

            if (i < obj2.len) {
                res += obj2.num[i];
            }

            tmp.num[i] = res % 10;
            carry = res / 10;
        }

        tmp.num[max_len] = carry;
        tmp.len = max_len + (carry ? 1 : 0);
        tmp.sign = obj1.sign;
    } else {
        size_t max_len = (obj1.len > obj2.len ? obj1.len : obj2.len);

        if (abs(obj1) >= abs(obj2)) {
            for (size_t i = 0; i < max_len; i++) {
                res = carry;

                if (i < obj1.len) {
                    res += obj1.num[i];
                }

                if (i < obj2.len) {
                    res -= obj2.num[i];
                }

                tmp.num[i] = (res + 10) % 10;

                if (tmp.num[i]) {
                    tmp.len = i + 1;
                }

                carry = (res < 0 ? -1 : 0);
            }

            tmp.sign = obj1.sign;
        } else {
            return obj2 + obj1;
        }
    }

    tmp.num[tmp.len + 1] = 0;

    return tmp;
}

bigint operator-(const bigint &obj1, const bigint &obj2)
{
    return obj1 + (-obj2);
}

bigint operator*(const bigint &obj1, const bigint &obj2)
{
    if (obj1 == 0 || obj2 == 0) {
        return 0;
    }

    bigint tmp;
    char res, carry = 0;

    if (obj1.len + obj2.len > MAX_LEN) {
        throw("Overflow");
        return 0;
    }

    for (size_t i = 0; i <= obj1.len + obj2.len; i++) {
        tmp.num[i] = 0;
    }

    for (size_t i = 0; i <= obj1.len; i++) {
        carry = 0;

        for (size_t j = 0; j <= obj2.len; j++) {
            res = tmp.num[i + j] + carry + obj1.num[i] * obj2.num[j];
            tmp.num[i + j] = res % 10;
            carry = res / 10;
        }
    }

    tmp.len = obj1.len + obj2.len - (tmp.num[obj1.len + obj2.len - 1] ? 0 : 1);
    tmp.sign = obj1.sign ^ obj2.sign;
    return tmp;
}

bigint operator/(const bigint &obj1, const bigint &obj2)
{
    bigint tmp, divident(0);
    int quot;

    for (long i = obj1.len - 1; i >= 0; i--) {
        if (divident < obj2) {
            divident = divident * 10 + obj1.num[i];
        }
        quot = 0;
        while ((quot + 1) * obj2 <= divident) {
            quot++;
        }
        tmp = tmp * 10 + quot;
        divident -= quot * obj2;
    }

    tmp.sign = obj1.sign ^ obj2.sign;

    return tmp;
}

bigint operator%(const bigint &obj1, const bigint &obj2)
{
    return obj1 - obj1 / obj2 * obj2;
}

// operatori de atribuire compusi
bigint &bigint::operator+=(const bigint &obj)
{
    *this = (*this) + obj;
    return *this;
}

bigint &bigint::operator-=(const bigint &obj)
{
    *this = (*this) - obj;
    return *this;
}

bigint &bigint::operator*=(const bigint &obj)
{
    *this = (*this) * obj;
    return *this;
}

bigint &bigint::operator/=(const bigint &obj)
{
    *this = (*this) / obj;
    return *this;
}

bigint &bigint::operator%=(const bigint &obj)
{
    *this = (*this) % obj;
    return *this;
}

// operatiru de egalitate
bool operator==(const bigint &obj1, const bigint &obj2)
{
    if (obj1.len != obj2.len) {
        return 0;
    }

    for (size_t i = 0; i < obj1.len; i++) {
        if (obj1.num[i] != obj2.num[i]) {
            return 0;
        }
    }

    return 1;
}

bool operator!=(const bigint &obj1, const bigint &obj2)
{
    return !(obj1 == obj2);
}

// operatori relationali
bool operator<(const bigint &obj1, const bigint &obj2)
{
    if (obj1.len < obj2.len) {
        return 1;
    }

    if (obj1.len > obj2.len) {
        return 0;
    }

    for (long i = obj1.len - 1; i >= 0; i--) {
        if (obj1.num[i] > obj2.num[i]) {
            return 0;
        }

        if (obj1.num[i] < obj2.num[i]) {
            return 1;
        }
    }

    return 0;
}

bool operator<=(const bigint &obj1, const bigint &obj2)
{
    return !(obj1 > obj2);
}

bool operator>(const bigint &obj1, const bigint &obj2)
{
    return obj2 < obj1;
}

bool operator>=(const bigint &obj1, const bigint &obj2)
{
    return !(obj1 < obj2);
}

// operatori de citire si scriere
istream &operator>>(istream &in, bigint &obj)
{
    char s[MAX_LEN + 1];
    in.getline(s, MAX_LEN + 1);
    obj = bigint(s);
    return in;
}

ostream &operator<<(ostream &out, const bigint &obj)
{
    if (obj.sign) {
        out << '-';
    }

    for (int i = obj.len - 1; i >= 0; i--) {
        out << (int)obj.num[i];
    }
    return out;
}

bigint euclid(bigint num1, bigint num2)
{
    bigint c;

    while(num2 != 0) {
        c = num1 % num2;
        num1 = num2;
        num2 = c;
    }

    return num1;
}

ifstream fin("numere2.in");
ofstream fout("numere2.out");

forward_list < pair < bigint, bigint > > v;

int main()
{
    bigint p, d = 2, k = 0;
    fin >> p;

    while (d * d <= p) {
        k = 0;

        while (p % d == 0) {
            p /= d;
            k++;
        }

        if (k != 0) {
            v.push_front(make_pair(d, k));
        }

        d++;
    }

    if (p > 1) {
        v.push_front(make_pair(p, 1));
    }

    bigint a = 1, b = v.front().second;
    for (auto it : v) {
        b = euclid(b, it.second);
    }

    for (auto it : v) {
        bigint pw = it.second / b;
        for (bigint i = 0; i < pw; i++) {
            a *= it.first;
        }
    }

    fout << a << '\n' << b;

    return 0;
}