【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

Sample Output

  24
  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)] 啦。
  至于卷积这个东西,当然是让我们膜拜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 
View Code

 

posted @ 2017-06-12 14:54  BearChild  阅读(110)  评论(0编辑  收藏  举报