P3803 [テンプレート]多項式乗算(FFT)
注意:この質問は3Sを開くが、1秒以内に終えることができるプログラムは、この質問は、一定の最適化をある程度必要とすることをお勧めしますが。
タイトル説明
次の多項式のN F(X)、及びm次多項式G(x)で与えられます。
畳み込みF(x)とG(X)のを要求します。
入出力フォーマット
入力フォーマット:2つの正の整数N、Mの最初の行。
高い係数F(X)にローから表される次のラインN + 1桁。
ローからハイ係数G(X)に示される次のラインm + 1桁)の。
出力フォーマット:行N + M +ローからハイ係数Fに示される1桁(X)* G(x)での。
サンプル入力と出力
説明
係数入力が0以上と以下9と同じであることを確認します。
$ nは、m個の\当量{10} ^ 6 $、20個のデータ点の総数、2S:データの100%まで。
データは、勾配を持っています。
スペースの制約:256メガバイト
高速フーリエ変換(FFT)高速フーリエ変換を変換します
情報のすべての種類は非常に明確に書かれている、何も言うことはありません。
次いで、高精度で小さい定数(部分)バイナリバタフライ演算において具現コード、およびフリップを総括。
ここで私は、コードをカプセル化し、3秒に、その後のオープンTLE ...... O2繰り返しポストカード。
#8
交流
2923ms / 78800キロバイト
9#
交流
2949ms / 81944キロバイト
その後、出力され-0問題。時間複雑 \(O(N \ログN )\)
#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
T data=0,w=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;
typedef vector<complex<double> > polynomial;
co double PI=acos(-1);
void Fourier_Transform(polynomial&a,int inverse){
int limit=a.size(),len=log2(limit);
// bit reserval
vector<int> bit_rev(limit);
for(int i=0;i<limit;++i) bit_rev[i]=bit_rev[i>>1]>>1|(i&1)<<len-1;
for(int i=0;i<limit;++i)if(i<bit_rev[i]) swap(a[i],a[bit_rev[i]]);
// Butterfly diagram
for(int step=1;step<limit;step<<=1){
double alpha=inverse*PI/step;
for(int k=0;k<step;++k){
complex<double> omega_k=exp(complex<double>(0,alpha*k));
for(int even_k=k;even_k<limit;even_k+=step<<1){
int odd_k=even_k+step;
complex<double> t=omega_k*a[odd_k];
a[odd_k]=a[even_k]-t,a[even_k]+=t;
}
}
}
if(inverse==-1)for(int i=0;i<limit;++i) a[i]/=limit;
}
int main(){
// freopen("LG3803.in","r",stdin),freopen("LG3803.out","w",stdout);
int n=read<int>(),m=read<int>();
polynomial a(n+1),b(m+1);
for(int i=0;i<=n;++i) read(a[i].real());
for(int i=0;i<=m;++i) read(b[i].real());
int limit=1;
while(limit<n+m+1) limit<<=1;
a.resize(limit),b.resize(limit);
Fourier_Transform(a,1),Fourier_Transform(b,1);
for(int i=0;i<limit;++i) a[i]*=b[i];
Fourier_Transform(a,-1);
for(int i=0;i<=n+m;++i) printf("%.0lf ",a[i].real()+1e-9); // edit 1:-0
return 0;
}