1. 程式人生 > >BZOJ2194 快速傅立葉之二 【fft】

BZOJ2194 快速傅立葉之二 【fft】

class real puts edge max math long long cst include

題目

請計算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,並且有 n < = 10 ^ 5。 a,b中的元素均為小於等於100的非負整數。

輸入格式

第一行一個整數N,接下來N行,第i+2..i+N-1行,每行兩個數,依次表示a[i],b[i] (0 < = i < N)。

輸出格式

輸出N行,每行一個整數,第i行輸出C[i-1]。

輸入樣例

5

3 1

2 4

1 1

2 4

1 4

輸出樣例

24

12

10

6

1

題解

和2179幾乎一模一樣
由於卷積的定義要求下標之和為常數,我們嘗試將原式變形,發現只要將a或者b反過來存就可以了

#include<iostream>
#include<cmath> #include<cstdio> #include<cstring> #include<complex> #include<algorithm> #define pi acos(-1) #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt) #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<‘ ‘; puts("");
using namespace std; const int maxn = 400005,maxm = 100005,INF = 1000000000; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57) {if (c == ‘-‘) flag = -1; c = getchar();} while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - ‘0‘; c = getchar();} return
out * flag; } typedef complex<double> E; E a[maxn],b[maxn]; int n,m,L,R[maxn]; void fft(E* a,int f){ for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]); for (int i = 1; i < n; i <<= 1){ E wn(cos(pi / i),f * sin(pi / i)); for (int j = 0; j < n; j += (i << 1)){ E w(1,0); for (int k = 0; k < i; k++,w *= wn){ E x = a[j + k],y = w * a[j + k + i]; a[j + k] = x + y; a[j + k + i] = x - y; } } } if (f == -1) for (int i = 0; i < n; i++) a[i] /= n; } int main(){ n = read(); n--; for (int i = 0; i <= n; i++){a[n - i] = read();b[i] = read();} m = n << 1; for (n = 1; n <= m; n <<= 1) L++; for (int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1)); fft(a,1); fft(b,1); for (int i = 0; i <= n; i++) a[i] *= b[i]; fft(a,-1); for (int i = (m >> 1); i >= 0; i--) printf("%d\n",(int)(a[i].real() + 0.1)); return 0; }

BZOJ2194 快速傅立葉之二 【fft】