1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
| // 더 많은 정보는 42jerrykim.github.io에서 확인할 수 있습니다.
#include <bits/stdc++.h>
using namespace std;
using cd = complex<double>;
const double PI = acos(-1.0);
static void fft(vector<cd> &a, bool invert) {
int n = (int)a.size();
static vector<int> rev;
static vector<cd> roots{cd(0, 0), cd(1, 0)};
if ((int)rev.size() != n) {
rev.assign(n, 0);
int k = __builtin_ctz(n);
for (int i = 0; i < n; i++) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
}
}
if ((int)roots.size() < n) {
int k = __builtin_ctz((int)roots.size());
roots.resize(n);
while ((1 << k) < n) {
double angle = 2 * PI / (1 << (k + 1));
for (int i = 1 << (k - 1); i < (1 << k); i++) {
roots[2 * i] = roots[i];
double ang = angle * (2 * i + 1 - (1 << k));
roots[2 * i + 1] = cd(cos(ang), sin(ang));
}
++k;
}
}
for (int i = 0; i < n; i++) {
if (i < rev[i]) swap(a[i], a[rev[i]]);
}
for (int len = 1; len < n; len <<= 1) {
for (int i = 0; i < n; i += 2 * len) {
for (int j = 0; j < len; j++) {
cd u = a[i + j];
cd v = a[i + j + len] * roots[len + j];
a[i + j] = u + v;
a[i + j + len] = u - v;
}
}
}
if (invert) {
reverse(a.begin() + 1, a.end());
for (cd &x : a) x /= n;
}
}
static vector<long long> convolution(const vector<int> &a, const vector<int> &b) {
int n1 = (int)a.size();
int n2 = (int)b.size();
int n = 1;
while (n < n1 + n2) n <<= 1;
vector<cd> fa(n), fb(n);
for (int i = 0; i < n1; i++) fa[i] = cd(a[i], 0);
for (int i = 0; i < n2; i++) fb[i] = cd(b[i], 0);
fft(fa, false);
fft(fb, false);
for (int i = 0; i < n; i++) fa[i] *= fb[i];
fft(fa, true);
vector<long long> res(n);
for (int i = 0; i < n; i++) res[i] = llround(fa[i].real());
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s, t;
if (!(cin >> s >> t)) return 0;
auto isZero = [](const string &x) {
for (char c : x) if (c != '0') return false;
return true;
};
if (isZero(s) || isZero(t)) { cout << 0 << '\n'; return 0; }
const int base = 1000; // 10^3
const int base_digits = 3; // group size
auto toBase = [&](const string &x) {
vector<int> v;
for (int i = (int)x.size(); i > 0; i -= base_digits) {
int l = max(0, i - base_digits);
int val = 0;
for (int j = l; j < i; j++) val = val * 10 + (x[j] - '0');
v.push_back(val);
}
return v; // least significant block first
};
vector<int> a = toBase(s);
vector<int> b = toBase(t);
vector<long long> c = convolution(a, b);
long long carry = 0;
for (size_t i = 0; i < c.size(); i++) {
long long cur = c[i] + carry;
c[i] = (int)(cur % base);
carry = cur / base;
}
while (carry > 0) { c.push_back((int)(carry % base)); carry /= base; }
while (c.size() > 1 && c.back() == 0) c.pop_back();
string out = to_string(c.back());
for (int i = (int)c.size() - 2; i >= 0; i--) {
string chunk = to_string((int)c[i]);
if ((int)chunk.size() < base_digits) out += string(base_digits - (int)chunk.size(), '0');
out += chunk;
}
cout << out << '\n';
return 0;
}
|