高精度

高精度

#include <bits/stdc++.h>
#define gc() getchar()
using namespace std;
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
typedef pair<int, int> pi;
typedef pair<i64, i64> PI;
const int N = 1e3 + 5;
const i64 mod = 1e9 + 7;
const ui64 basic = 233;
const int inf = 1e9;
const int mof = 0x3f3f3f3f;
const i64 INF = 1e16;
const i64 MOF = 0x3f3f3f3f3f3f3f3f;

void init() {
}

// namespace IO {
// 	template<typename T>
// 	inline void read(T &x) {
// 		bool f = 1;
// 		x = 0;
// 		char ch = gc();
// 		while (ch < '0' || ch > '9') {
// 			if (ch == '-')f = 0;
// 			ch = gc();
// 		}
// 		while (ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + (ch & 15), ch = gc();
// 		x = f ? x : -x;
// 	}

// 	template<typename T>
// 	inline void write(T x) {
// 		if (x < 0) putchar('-'), x = -x;
// 		if (x > 9) write(x / 10);
// 		putchar(('0' + x % 10));
// 	}

// 	template <typename T, typename ...Args>
// 	inline void read(T &x, Args &...args) {
// 		read(x);
// 		read(args...);
// 	}

// 	template<typename T>
// 	inline void write(T x, char c) {
// 		write(x), putchar(c);
// 	}
// }
// using namespace IO;

struct Big{
    const i64 DLEN = 9;// 压位的大小
    const i64 MAX = 999999999LL;// 压位完的这个数最大为多少
    i64 len;// 这个数的长度
    bool is_;// false表示次数为非负数,否则为负数
    vector<i64> a;

    inline void init() {// 初始化
        len = 0;
        is_ = false;
        a.clear();
    }

    inline static bool judge0(Big& A) {// 判断这个数是否为0
        if (A.len == 1 && A.a[0] == 0) return true;
        return false;
    }

    inline static bool judge1(Big& A) {// 判断这个数是否为1
        if (A.len == 1 && A.a[0] == 1) return true;
        return false;
    }

    inline static bool judge2(Big& A) {// 判断这个数是否为偶数
        if (A.a[0] & 1) return false;
        return true;
    }

    Big();// 无参构造
    Big(i64);// 数字构造
    Big(const Big&);// 结构体构造
    Big(const string&);// 字符串构造

    inline Big operator+ (const Big&) const;// 高精度加高精度,时间复杂度O(n)
    inline Big operator- (const Big&) const;// 高精度减高精度,时间复杂度O(n)
    inline Big operator* (const Big&) const;// 高精度乘高精度,时间复杂度O(n*m)
    inline Big operator/ (const i64&) const;// 高精度除低精度,时间复杂度O(n)
    inline Big operator/ (const Big&) const;// 高精度除高精度,还没写,之后会更新
    inline i64 operator% (const i64&) const;// 高精度取模低精度,时间复杂度O(n)
    inline i64 operator% (const Big&) const;// 高精度取模高精度,还没写,之后会更新
    inline Big operator^ (i64) const;// 高精度的低精度次幂,时间复杂度O(nlogm)
    inline Big& operator= (const Big&);// 赋值
    inline bool operator== (const Big&) const;// 判断是否相等
    inline bool operator!= (const Big&) const;// 判断是否不相等
    inline bool operator< (const Big&) const;// 判断是否小于
    inline bool operator> (const Big&) const;// 判断是否大于

    inline static void swap(Big&, Big&);// 交换两个数
    inline static Big gcd(Big&, Big&);// 求两个数的gcd,时间复杂度O(nlog(n))
    inline static Big lcm(Big&, Big&);// 求两个数的lcm,时间复杂度根据高精度除以高精度的复杂度有关系,还没写,之后会更新
    inline static Big Sqrt(Big&);// 求这个数的平方根,还没写,之后会更新
    inline void print() const;// 输出这个数
};

Big::Big() {
    len = 0;
    is_ = false;
    a.clear();
}

Big::Big(i64 A) {
    if (A != 0) {
        len = 0;
        is_ = false;
        if (A < 0) is_ = true, A = -A;
        while (A > MAX) {
            i64 sum = A - A / (MAX + 1) * (MAX + 1);
            A /= MAX + 1;
            len++;
            a.push_back(sum);
        }
        if (A) {
            len++;
            a.push_back(A);
        }
    } else {
        len = 1;
        is_ = false;
        a.push_back(0);
    }
}

Big::Big(const Big& A) : is_(A.is_), len(A.len), a(A.a) {}

Big::Big(const string& A) {
    len = 0;
    is_ = true;
    if (isdigit(A[0]) || A[0] != '-') is_ = false;
    i64 le = A.size();
    i64 sum = 0, cnt = 0;
    i64 en = isdigit(A[0]) ? 0 : 1;
    for (i64 i = le - 1; i >= en; i -= DLEN) {
        i64 m = min(DLEN, i - en + 1);
        i64 sum = stoi(A.substr(i - m + 1, m));
        len++;
        a.push_back(sum);
    }
}

inline Big Big::operator+ (const Big& b) const {
    Big A = *this, B = b;
    if (A.is_ && !B.is_) {
        A.is_ = false;
        return B - A;
    }
    if (!A.is_ && B.is_) {
        B.is_ = false;
        return A - B;
    }
    Big res;
    res.is_ = A.is_;
    i64 le = max(A.len, B.len), mark = 0;
    for (i64 i = 0; i < le; i++) {
        i64 sum = mark;
        if (i < len) sum += A.a[i];
        if (i < B.len) sum += B.a[i];
        if (sum <= MAX) {
            mark = 0;
        } else {
            mark = 1;
            sum -= MAX + 1;
        }
        res.len++;
        res.a.push_back(sum);
    }
    if (mark) {
        res.len++;
        res.a.push_back(mark);
    }
    while (res.len > 1 && res.a.back() == 0) {
        res.len--;
        res.a.pop_back();
    }
    if (res.len == 1 && res.a[0] == 0) res.is_ = false;
    return res;
}

inline Big Big::operator- (const Big& b) const {
    Big A = *this, B = b;
    if (!A.is_ && B.is_) {
        B.is_ = false;
        return A + B;
    }
    if (A.is_ && !B.is_) {
        B.is_ = true;
        return A + B;
    }
    Big res;
    if (A < B) {
        res.is_ = true;
        swap(A, B);
    }
    i64 le = max(A.len, B.len), mark = 0;
    for (i64 i = 0; i < le; i++) {
        i64 sum = mark;
        if (i < A.len) {
            sum += A.a[i];
        }
        if (i < B.len) {
            sum -= B.a[i];
        }
        if (sum < 0) {
            mark = -1;
            sum += MAX + 1;
        } else {
            mark = 0;
        }
        res.len++;
        res.a.push_back(sum);
    }
    while (res.len > 1 && res.a.back() == 0) {
        res.len--;
        res.a.pop_back();
    }
    if (res.len == 1 && res.a[0] == 0) res.is_ = false;
    return res;
}

inline Big Big::operator* (const Big& b) const {
    Big res;
    Big A = *this, B = b;
    res.is_ = A.is_ != B.is_;
    for (i64 i = 0; i < A.len; i++) {
        i64 mark = 0;
        for (i64 j = 0; j < B.len; j++) {
            i64 sum = A.a[i] * B.a[j] + mark;
            if (i + j < res.len) {
                sum += res.a[i + j];
                if (sum <= MAX) {
                    mark = 0;
                    res.a[i + j] = sum;
                } else {
                    mark = sum / (MAX + 1);
                    sum -= mark * (MAX + 1);
                    res.a[i + j] = sum;
                }
            } else {
                res.len++;
                if (sum <= MAX) {
                    mark = 0;
                    res.a.push_back(sum);
                } else {
                    mark = sum / (MAX + 1);
                    sum -= mark * (MAX + 1);
                    res.a.push_back(sum);
                }
            }
        }
        if (mark) {
            if (i + B.len < res.len) {
                res.a[i + B.len] = mark;
            } else {
                res.len++;
                res.a.push_back(mark);
            }
        }
    }
    while (res.len > 1 && res.a.back() == 0) {
        res.len--;
        res.a.pop_back();
    }
    if (res.len == 1 && res.a[0] == 0) res.is_ = false;
    return res;
}

inline Big Big::operator/ (const i64& b) const {
    Big res;
    Big A = *this;
    i64 B = b;
    res.is_ = A.is_ || B < 0;
    i64 sum = 0;
    B = abs(B);
    res.len = A.len;
    res.a.assign(A.len, 0);
    for (i64 i = A.len - 1; i >= 0; i--) {
        i64 ans = (sum * (MAX + 1) + A.a[i]) / B;
        res.a[i] = ans;
        sum = sum * (MAX + 1) + A.a[i] - B * ans;
    }
    while (res.len > 1 && res.a.back() == 0) {
        res.len--;
        res.a.pop_back();
    }
    if (res.len == 1 && res.a[0] == 0) res.is_ = false;
    return res;
}

inline i64 Big::operator% (const i64& b) const {
    Big A = *this;
    i64 B = b;
    i64 ans = 0;
    for (i64 i = A.len - 1; i >= 0; i--) {
        ans = ans * (MAX + 1) + A.a[i];
        if (ans >= B) ans %= B;
    }
    if (A.is_) ans = -ans;
    ans = (ans + B) % B;
    return ans;
}

inline Big Big::operator^ (i64 B) const {
    Big res(1), A = *this;
    while (B) {
        if (B & 1) {
            res = res * A;
        }
        A = A * A;
        B >>= 1;
    }
    return res;
}

inline Big& Big::operator= (const Big& B) {
    a.clear();
    len = B.len;
    is_ = B.is_;
    for (auto p : B.a) {
        a.push_back(p);
    }
    return *this;
}

inline bool Big::operator== (const Big& B) const {
    if (is_ != B.is_ || len != B.len) return false;
    for (int i = len - 1; i >= 0; i--) {
        if (a[i] != B.a[i]) return false;
    }
    return true;
}

inline bool Big::operator!= (const Big& B) const {
    if (is_ != B.is_ || len != B.len) return true;
    for (int i = len - 1; i >= 0; i--) {
        if (a[i] != B.a[i]) return true;
    }
    return false;
}

inline bool Big::operator< (const Big& B) const {
    if (is_ != B.is_) return is_;
    if (len != B.len) return (is_ ? len > B.len : len < B.len);
    for (int i = len - 1; i >= 0; i--) {
        if (a[i] != B.a[i]) return (is_ ? a[i] > B.a[i] : a[i] < B.a[i]);
    }
    return false;
}

inline bool Big::operator> (const Big& B) const {
    if (is_ != B.is_) return !is_;
    if (len != B.len) return (!is_ ? len > B.len : len < B.len);
    for (int i = len - 1; i >= 0; i--) {
        if (a[i] != B.a[i]) return (!is_ ? a[i] > B.a[i] : a[i] < B.a[i]);
    }
    return false;
}

inline void Big::swap(Big& A, Big& B) {
    Big res = A;
    A = B;
    B = res;
}

Big Big::gcd(Big& a, Big& b) {
    Big res(1), A = a, B = b;
    while (true) {
        if (A < B) swap(A, B);
        if (judge1(B)) break;
        if (judge0(B)) {
            res = res * A;
            break;
        }
        if (judge2(A) && judge2(B)) {
            res = res * Big(2);
            A = A / 2;
            B = B / 2;
        } else if (judge2(A)) {
            A = A / 2;
        } else if (judge2(B)) {
            B = B / 2;
        } else {
            A = A - B;
        }
    }
    return res;
}

inline void Big::print() const {
    if (is_) printf("-");
    printf("%lld", a[len - 1]);
    for (int i = len - 2; i >= 0; i--) {
        printf("%0*lld", DLEN, a[i]);
    }
}

void solve() {
    string a, b;
    cin >> a >> b;
    Big A(a), B(b);
    Big ans = Big::gcd(A, B);
    ans.print();
}

int main() {
    // ios::sync_with_stdio(0);
    // cin.tie(0), cout.tie(0);
    init();
    int _ = 1;
    // std::cin >> _;
    while (_--) {
        solve();
    }
    
    return 0;
}

\(FFT\) 算法高精度乘法

posted @ 2024-09-11 21:33  grape_king  阅读(24)  评论(0)    收藏  举报