高精度
#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\) 算法高精度乘法