FFT
#include<iostream>
#include<cmath>
using namespace std;
namespace IO{
struct INITDEVICE{INITDEVICE(){ios::sync_with_stdio(false);cin.tie(nullptr);}};
static INITDEVICE ID;
inline int gc(){return cin.rdbuf()->sbumpc();}
inline void pc(char c){cout.rdbuf()->sputc(c);}
template<typename T>void rd(T &x){
x=0;int f=1,c=gc();
while('0'>c||c>'9'){
if(c==EOF){cerr<<"IE\n";exit(EXIT_FAILURE);}
if(c=='-')f*=-1;
c=gc();
}while('0'<=c&&c<='9'){
x=x*10+c-'0';
c=gc();
}x*=f;
}
template<typename T>void wt(T x){
if(x<0)pc('-');
static int d,tp,stk[40];
tp=0;
do{
d=x%10;
stk[++tp]=(d<0?-d:d)+'0';
x/=10;
}while(x);
while(tp)pc(stk[tp--]);
}
}using namespace IO;
typedef long long ll;
typedef double db;
typedef long double ld;
constexpr int N=4e6+5;
const db pi=acos(-1);
struct cplx{db x,y;};
inline cplx operator +(const cplx& A,const cplx& B){return cplx{A.x+B.x,A.y+B.y};}
inline cplx operator -(const cplx& A,const cplx& B){return cplx{A.x-B.x,A.y-B.y};}
inline cplx operator *(const cplx& A,const cplx& B){return cplx{A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x};}
struct poly{
cplx p[N];
int deg;
}f,g;
int len=1;
int rev[N];//i在二进制表示下倒过来得到的数字,因为这是迭代版fft(位逆序)
/*
为什么一定是位逆序?
因为每次“按奇偶拆”看的是下标的最低位:
最低位是 0 → 去偶数组;
最低位是 1 → 去奇数组。
那么显然,每次分组相当于一次排序(类似基数排序),原下标是高位为第一关键字升序排序的,
而新的下标是以低位为第一关键字排序的。
所以将位逆序直接符合要求
*/
void fft(poly &a,int ind){
for(int i=0;i<len;++i){
if(i<rev[i]){//是对称的,保证只交换一次
swap(a.p[i],a.p[rev[i]]);
}
}
for(int sublen=1;sublen<len;sublen<<=1){
cplx wn={cos(pi/sublen),sin(pi/sublen)*ind};//欧拉公式
for(int i=0;i<len;i+=(sublen<<1)){
cplx wk={1,0};
for(int j=0;j<sublen;++j,wk=wk*wn){
cplx x=a.p[i+j],y=wk*a.p[i+sublen+j];
a.p[i+j]=x+y;
a.p[i+sublen+j]=x-y;
}
}
}
}
inline void global(){
}
namespace tqy{
inline void init(){
rd(f.deg);
rd(g.deg);
for(int i=0;i<=f.deg;++i){
rd(f.p[i].x);
}
for(int i=0;i<=g.deg;++i){
rd(g.p[i].x);
}
}
inline void solve(){
int k=0;
while(len<=f.deg+g.deg)len<<=1,++k;
for(int i=0;i<len;++i){
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
}
fft(f,1);
fft(g,1);
for(int i=0;i<len;++i){
f.p[i]=f.p[i]*g.p[i];
}
fft(f,-1);
for(int i=0;i<=f.deg+g.deg;++i){
wt(int(f.p[i].x/len+0.5)),pc(' ');//+0.5等价于四舍五入
}
pc('\n');
}
}
signed main(){
global();
int T=1;
while(T--)tqy::init(),tqy::solve();
return 0;
}
/*
*/
初学FFT的话1可以看洛谷收藏夹命令方块作的文章,讲的挺细致的

浙公网安备 33010602011771号