Bzoj2194 快速傅立叶之二

 

 

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1147  Solved: 658

Description

请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 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

 

Source

 

 

把b[]数组逆序,则sigma内下标和为定值,可以套用FFT

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<complex>
 6 #define pi acos(-1)
 7 using namespace std;
 8 const int mxn=100010*3;
 9 typedef complex<double>com;
10 com a[mxn],b[mxn];
11 int rev[mxn];
12 int n,l;
13 void FFT(com* a,int flag){
14     int i,j,x;
15     for(i=0;i<n;i++)
16         if(rev[i]>i)swap(a[rev[i]],a[i]);
17     for(i=1;i<n;i<<=1){
18         com wn(cos(pi/i),flag*sin(pi/i));
19         for(j=0;j<n;j+=(i<<1)){
20             com w(1,0);
21             for(int k=0;k<i;k++,w*=wn){
22                 com x=a[j+k],y=w*a[i+j+k];
23                 a[j+k]=x+y;
24                 a[i+j+k]=x-y;
25             }
26         }
27     }
28     if(flag==-1)for(i=0;i<n;i++)a[i]/=n;
29 }
30 int main(){
31     int i,j;
32     scanf("%d",&n);
33     for(i=0;i<n;i++)scanf("%lf%lf",&a[i],&b[n-i-1]);
34     int m=n<<1;
35     for(n=1;n<m;n<<=1)l++;
36     for(i=0;i<n;i++){
37         rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
38     }
39     FFT(a,1);FFT(b,1);
40     for(i=0;i<n;i++)a[i]*=b[i];
41     FFT(a,-1);
42     m>>=1;
43     for(i=m-1;i<2*m-1;i++)
44         printf("%d\n",(int)(a[i].real()+0.5));
45     return 0;
46 }

 

posted @ 2017-01-31 19:28  SilverNebula  阅读(197)  评论(0编辑  收藏  举报
AmazingCounters.com