题意:给出一个a和b,长度不超过5e4,输出a*b的结果
题解:直接上一波快速傅里叶变化-FFT即可~
//以下模板为结构体内为快速傅里叶变换模板
//结构体外为借助该模板实现的高精度乘法计算
//以下为多项式相乘(高精度可以看作x=10的多项式相乘)的快速傅里叶变换的使用简述:
//设一个a的正傅里叶变换为DEF(a),逆傅里叶变换为IDFT(a)
//并且有:多项式a和多项式b的多项式相乘的中间结果=IFDFT(DFT(a)*DFT(b))
//其中*运算为数组中的对应项进行复数乘法运算
//多项式a和多项式b相乘的结果等于中间结果除以多项式的长度n
//注意所有的数都必须使用浮点数,并且不能太大(浮点数会出现误差)
//注意长度要足够大并且为2的幂,不足长度补0
//高精度乘法还必须将运算结果进行进位
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 4e5 + 500;
#define PI acos(-1.0)
struct Complex //复数类
{
double a, b;//b(i)+a
Complex() {}
Complex(double aa, double bb) :a(aa), b(bb) {}
Complex operator +(Complex p)
{
double c = p.a, d = p.b;
return Complex(a + c, b + d);
}
Complex operator *(Complex p)
{
double c = p.a, d = p.b;
return Complex(a*c - b*d, b*c + a*d);
}
Complex operator -(Complex p)
{
double c = p.a, d = p.b;
return Complex(a - c, b - d);
}
};
struct FFT
{
Complex _P[maxn];
void build(Complex P[], int n, int m, int curr, int &cnt)
{
if (m == n) _P[curr] = P[cnt++];
else
{
build(P, n, m * 2, curr, cnt);
build(P, n, m * 2, curr + m, cnt);
}
}
void solve(Complex P[], int n, int oper)//对数组P做一次快速傅里叶变换
{ //P为待变换的数组,n为长度,oper为1则为正变换,-1为负变换
int cnt = 0;
build(P, n, 1, 0, cnt);
for (int i = 0; i < n; i++)
P[i] = _P[i];
for (int d = 0; (1 << d) < n; d++)
{
int m = 1 << d;
int m2 = m * 2;
double p0 = PI / m*oper;
Complex unit_p0 = Complex(cos(p0), sin(p0));
for (int i = 0; i < n; i += m2)
{
Complex unit = Complex(1, 0);
for (int j = 0; j < m; j++)
{
Complex &P1 = P[i + j + m];
Complex &P2 = P[i + j];
Complex t = unit*P1;
P1 = P2 - t;
P2 = P2 + t;
unit = unit*unit_p0;
}
}
}
}
}F;
Complex p1[maxn], p2[maxn];
char s1[maxn], s2[maxn];
int main()
{
while (~scanf("%s%s", s1, s2))
{
memset(p1, 0, sizeof(p1));
memset(p2, 0, sizeof(p2));
int len1 = strlen(s1), len2 = strlen(s2);
if (len1 == 1 && s1[0] == '0' || len2 == 1 && s2[0] == '0') //注意0的情况
{
cout << 0 << endl; continue;
}
for (int i = 0; i < len1; i++)
p1[i].a = (s1[len1 - i - 1] - '0');
for (int i = 0; i < len2; i++)
p2[i].a = (s2[len2 - i - 1] - '0');
int anslen = 1; //anslen为给ans留的长度,不足补0
while (anslen < len1 * 2 || anslen < len2 * 2)
anslen <<= 1;
F.solve(p1, anslen, 1);
F.solve(p2, anslen, 1);
for (int i = 0; i < anslen; i++)
p1[i] = p1[i] * p2[i];
F.solve(p1, anslen, -1);
int p = 0;
for (int i = 0; i < anslen; i++)
{
p1[i].a /= anslen;
int d = p1[i].a;
//避免浮点数转整数的精度误差
if (d - p1[i].a > 0.5)d--;
if (p1[i].a - d > 0.5)d++;
d += p;
p = d / 10;
d %= 10;
p1[i].a = d;
}
bool flag = false;
for (int i = anslen; i >= 0; i--)
{
if (p1[i].a >= 0.5)flag = true;
if (flag)printf("%.0lf", p1[i].a);
}
cout << endl;
}
return 0;
}