【BZOJ2194】快速傅立叶之二 [FFT]
快速傅立叶之二
Time Limit: 10 Sec Memory Limit: 259 MB[Submit][Status][Discuss]
Description
请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n。 a,b中的元素均为小于等于100的非负整数。
Input
第一行一个整数N,接下来N行,第i+2..i+N-1行,每行两个数,依次表示a[i],b[i] (0 < = i < N)。
Output
输出N行,每行一个整数,第i行输出C[i-1]。
Sample Input
5
3 1
2 4
1 1
2 4
1 4
3 1
2 4
1 1
2 4
1 4
Sample Output
24
12
10
6
1
12
10
6
1
HINT
n < = 10 ^ 5
Solution
显然是运用FFT,看到题目里 b 的下标为 i-k,于是乎我们就要想一个办法,把它弄成卷积的形式。
然后翻转一下,下标就变成了(n-1)-(i-k)。那 Ans[n-1+k]=Σa[i]*b[(n-1)-(i-k)] 啦。
然后翻转一下,下标就变成了(n-1)-(i-k)。那 Ans[n-1+k]=Σa[i]*b[(n-1)-(i-k)] 啦。
至于卷积这个东西,当然是让我们膜拜AireenYe啦!(←_←戳名字有惊喜)
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<map> 9 using namespace std; 10 typedef long long s64; 11 12 const int ONE = 5e5+5; 13 const double Pi = acos(-1.0); 14 15 int n, m; 16 int tn, tl; 17 int bitRev[ONE]; 18 19 struct Complex 20 { 21 double r, i; 22 Complex() {} 23 Complex(double _r, double _i) 24 : r(_r), i(_i) {} 25 friend Complex operator +(Complex a, Complex b) 26 { 27 return Complex(a.r + b.r, a.i + b.i); 28 } 29 friend Complex operator -(Complex a, Complex b) 30 { 31 return Complex(a.r - b.r, a.i - b.i); 32 } 33 friend Complex operator *(Complex a, Complex b) 34 { 35 return Complex(a.r*b.r - a.i*b.i, a.r*b.i + a.i*b.r); 36 } 37 }a[ONE], b[ONE]; 38 39 int get() 40 { 41 int res=1,Q=1;char c; 42 while( (c=getchar())<48 || c>57 ) 43 if(c=='-')Q=-1; 44 res=c-48; 45 while( (c=getchar())>=48 && c<=57 ) 46 res=res*10+c-48; 47 return res*Q; 48 } 49 50 51 void FFT_init(int n) 52 { 53 tn = 1, tl = 0; 54 while(tn < n) 55 tn <<= 1, tl ++; 56 for(int i = 0; i < tn; i++) 57 { 58 int l = bitRev[i >> 1] >> 1; 59 int r = (i & 1) << (tl - 1); 60 bitRev[i] = l | r; 61 } 62 } 63 64 void FFT(Complex *a, int rev) 65 { 66 for(int i = 0; i < tn; i++) 67 { 68 int r = bitRev[i]; 69 if(i < r) swap(a[i], a[r]); 70 } 71 72 for(int k = 1; k < tn; k <<= 1) 73 { 74 Complex wn(cos(Pi / k), rev * sin(Pi / k)); 75 for(int s = 0; s < tn; s += k<<1) 76 { 77 Complex w(1, 0); 78 for(int i = s; i < s + k; i++) 79 { 80 Complex f1 = a[i], f2 = w * a[i + k]; 81 a[i] = f1 + f2; 82 a[i + k] = f1 - f2; 83 w = w * wn; 84 } 85 } 86 } 87 } 88 89 int main() 90 { 91 n = get(); 92 for(int i=0; i<n; i++) 93 a[i].r = get(), b[n-1-i].r = get(); 94 95 FFT_init(n + n + 1); 96 97 FFT(a, 1); FFT(b, 1); 98 for(int i=0; i<tn; i++) 99 a[i] = a[i] * b[i]; 100 FFT(a, -1); 101 102 for(int i=n-1; i<n+n-1; i++) 103 printf("%d\n", (int)(a[i].r / tn + 0.5)); 104 105 } 106