[高速フーリエ変換--FFT]
2056 ワード
BZOJ 2199:FFT快速フーリエ
果題
BZOJ 194:C[k]=sigma(a[i]*b[i-k])のうちk<=iiとi-kに奇妙なつながりがあることに気づいた
bを反転してみてはいかがでしょうか
そしてボリュームになりました.の
テンプレートを貼る
果題
BZOJ 194:C[k]=sigma(a[i]*b[i-k])のうちk<=i
bを反転してみてはいかがでしょうか
そしてボリュームになりました.の
テンプレートを貼る
#include
#define maxn 500010
using namespace std;
struct cpx{
double r, i;
cpx(double a=0, double b=0):r(a), i(b){}
cpx operator+(const cpx& k)const{return cpx(r+k.r, i+k.i);}
cpx operator-(const cpx& k)const{return cpx(r-k.r, i-k.i);}
cpx operator*(const cpx& k)const{return cpx(r*k.r-i*k.i, r*k.i+i*k.r);}
cpx operator/(const double& n)const{return cpx(r/n, i/n);}
}A[maxn], B[maxn], P[maxn];
int n, l, k, a[maxn], b[maxn], c[maxn], r[maxn];
int rev(int a){
int ret = 0;
for(int i = 0; i < l; i ++){
ret = ret<<1|(a&1);
a >>= 1;
}
return ret;
}
void Init(){
scanf("%d", &n);k = n;
for(int i = 0; i < n; i ++)
scanf("%d%d", &a[i], &c[i]);
for(int i = 0; i < n; i ++)
b[n-i-1] = c[i];
for(int i = 0; i < n; i ++)
A[i].r = a[i], B[i].r = b[i];
int m = n << 1;
for(n = 1, l = 0; n <= m; n <<= 1, l ++);
for(int i = 0; i < n; i ++)
r[i] = rev(i);
}
const double pi = 3.1415926535;
void FFT(cpx A[], int n, int t){
for(int i = 0; i < n; i ++)P[r[i]] = A[i];
for(int i = 0; i < n; i ++)A[i] = P[i];
for(int k = 2; k <= n; k <<= 1){
cpx wn = cpx(cos(2*pi/k), t*sin(2*pi/k));
for(int i = 0; i < n; i += k){
cpx w = cpx(1, 0);
for(int j = 0; j < k>>1; j ++){
cpx T = A[i+j+(k>>1)] * w;
A[i+j+(k>>1)] = A[i+j] - T;
A[i+j] = A[i+j] + T;
w = w * wn;
}
}
}
if(t == -1)for(int i = 0; i < n; i ++)A[i] = A[i] / n;
}
int main(){
Init();
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);
for(int i = k - 1; i < 2 * k - 1; i ++){
int ret = A[i].r + 0.2;
printf("%d
", ret);
}
return 0;
}