这个标题是唬人玩儿的,虽然这题。。。名副其实
题意
这道题题意是大整数乘法。多组输入,每次输入两个数,一直处理到EOF为止。每组输入的数字的长度不超过50000。
思路
开头就已经写清楚了,这是个快速傅立叶变换的板题。当然,不知道压个八九位用long long
能不能暴力过QwQ
FFT本来就是处理多项式乘法的系数的,多项式乘法的系数运算恰好和整数乘法一致,所以就分别把两个数反转,然后用FFT求出它们相乘以后的值,然后再反转回来。
不要忘记它们做完乘法后可能会出现进位,所以记得处理进位(我的第一次WA)
然后别忘了初始化(第二次WA)
另外就是HDU的cmath
库里没有M_PI
(这得多老了),所以自定义一下PI
(下面这个值是我直接把M_PI
给复制过来了)。
FFT的板子是从OI-Wiki抄的,复数是我自己写的。
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
const double PI = 3.14159265358979323846264338327950288;
using namespace std;
const int maxn = 4e5 + 5;
int rev[maxn];
struct Complex {
double x, y;
Complex(double x = 0.0, double y = 0.0): x(x), y(y) {}
Complex operator + (const Complex &rhs) {
return Complex(this->x + rhs.x, this->y + rhs.y);
}
Complex operator - (const Complex &rhs) {
return Complex(this->x - rhs.x, this->y - rhs.y);
}
Complex operator * (const Complex &rhs) {
return Complex(this->x * rhs.x - this->y * rhs.y, this->x * rhs.y + this->y * rhs.x);
}
Complex operator / (const double rhs) {
return Complex(this->x / rhs, this->y / rhs);
}
};
void change(Complex y[], int len) {
for (int i = 0; i < len; i++) {
rev[i] = rev[i >> 1] >> 1;
if (i & 1)
rev[i] |= len >> 1;
}
for (int i = 0; i < len; i++) {
if (i < rev[i])
swap(y[i], y[rev[i]]);
}
}
void FFT(Complex y[], int len, int on) {
change(y, len);
for (int h = 2; h <= len; h <<= 1) {
Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h));
for (int j = 0; j < len; j += h) {
Complex w(1, 0);
for (int k = j; k < j + h / 2; k++) {
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}
if (on == -1) {
for (int i = 0; i < len; i++) {
y[i].x /= len;
}
}
}
char str1[maxn], str2[maxn];
Complex a[maxn], b[maxn];
int n, m, limit;
int ans[maxn];
void Assign(char *str, Complex x[], int len) {
for (int i = 0; i < len; i++) {
x[i].x = (double)(str[len - i - 1] - '0');
x[i].y = 0.0;
}
}
inline void init() {
for (int i = n; i <= limit; i++) a[i].x = a[i].y = 0.0;
for (int i = m; i <= limit; i++) b[i].x = b[i].y = 0.0;
memset(ans, 0, (limit << 2));
}
int main() {
while (scanf("%s%s", str1, str2) == 2) {
n = strlen(str1);
m = strlen(str2);
limit = 1;
while (limit <= n + m) limit <<= 1;
init();
Assign(str1, a, n);
Assign(str2, b, m);
FFT(a, limit, 1);
FFT(b, limit, 1);
for (int i = 0; i < limit; i++)
a[i] = a[i] * b[i];
FFT(a, limit, -1);
for (int i = 0; i < limit; i++)
ans[i] = int(a[i].x + 0.5);
for (int i = 0; i < limit; i++) {
ans[i + 1] += ans[i] / 10;
ans[i] %= 10;
}
// 这里len必须初始化为n + m - 1,因为上一次n + m的值可能不为0,而且init的时候没有处理n + m - 1后面的数据
// 就这一个破地方我调试了半个小时
// 说到底还是太菜QAQ
int len = n + m - 1;
while (!ans[len] && len > 0) len--;
for (int i = len; i >= 0; i--)
putchar(ans[i] + '0');
putchar('
');
}
return 0;
}