P1919 【模板】高精度乘法 | A*B Problem 升级版 (FFT)
题目描述
给你两个正整数 a,ba,ba,b,求 a×ba \times ba×b。
输入格式
第一行一个正整数,表示 aaa;
第二行一个正整数,表示 bbb。
输出格式
输出一行一个整数表示答案。
输入输出样例 #1
输入 #1
83517934
327830610
输出 #1
27379735249159740
说明/提示
【数据范围】
1≤a,b≤1010000001\le a,b \le 10^{1000000}1≤a,b≤101000000
可能需要一定程度的常数优化。
数据由 NaCly_Fish 重造
思路
不难发现,数据量不允许适用高精度乘法,所以使用FFT将原本的 O(n2)O(n^2)O(n2) 的复杂度降低为 O(nlogn)O(nlogn)O(nlogn) 的复杂度,将数字的每一位转换成0-9的系数,然后直接套FFT模板求出每一位相乘的结果,然后进行位数处理。
题解
#include <bits/stdc++.h>
using namespace std;
const int N=3e6+10;
const double PI=acos(-1);
int ans[N];
struct cpx{double x, y;cpx operator+(const cpx& t)const{return {x+t.x, y+t.y};}cpx operator-(const cpx& t)const{return {x-t.x, y-t.y};}cpx operator*(const cpx& t)const{return {x*t.x-y*t.y, x*t.y+y*t.x};}
}A[N], B[N];
int R[N];void FFT(cpx A[],int n,int op){for(int i=0; i<n; ++i)R[i] = R[i/2]/2 + ((i&1)?n/2:0);for(int i=0; i<n; ++i)if(i<R[i]) swap(A[i],A[R[i]]); for(int i=2; i<=n; i<<=1){cpx w1({cos(2*PI/i),sin(2*PI/i)*op});for(int j=0; j<n; j+=i){cpx wk({1,0});for(int k=j; k<j+i/2; ++k){cpx x=A[k], y=A[k+i/2]*wk;A[k]=x+y; A[k+i/2]=x-y; wk=wk*w1;}}}
}void solve(){string a,b;cin>>a>>b;int n = a.size()-1;int m = b.size()-1;for(int i=0; i<=n; i++){A[i].x=a[n-i]-'0'; }for(int i=0;i<=m;i++){B[i].x=b[m-i]-'0';}for(m=n+m,n=1;n<=m;n<<=1);FFT(A,n,1); FFT(B,n,1);for(int i=0;i<n;++i)A[i]=A[i]*B[i];FFT(A,n,-1);int t=0;int k=0;for(int i=0;i<n||t;++i){t+=(A[i].x/n+0.5);ans[k++]=t%10;t/=10;}while(k>1&&!ans[k-1])k--;for(int i=k-1;i>=0;i--)cout<<ans[i];cout<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t=1;// cin>>t;while(t--){solve();}return 0;
}
