BZOJ 2194: 快速傅立叶之二【FFT】

2194: 快速傅立叶之二

【题目描述】
传送门

【题解】

先将B数组翻转,然后套一下FFT的板子就好了。

代码如下

#include<cstdio>
#include<cmath>
#include<cctype>
#include<complex>
#define CP complex<double>
#define MAXN 400005
using namespace std;
const double PI=acos(-1.0);
int n,rev[MAXN];
CP a[MAXN],b[MAXN];
int read(){
    int ret=0;char ch=getchar();bool f=1;
    for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
    for(; isdigit(ch);ch=getchar()) ret=(ret<<3)+(ret<<1)+ch-48;
    return f?ret:-ret;
}
void Get_rev(int bit){
    for(int i=0;i<(1<<bit);i++)
    rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(CP *a,int Len,int dft){
    for(int i=0;i<Len;i++)
    if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(int step=1;step<Len;step<<=1){
        CP WN=exp(CP(0,dft*PI/step));
        for(int j=0;j<Len;j+=(step<<1)){
            CP WNK(1,0);
            for(int k=j;k<j+step;k++){
                CP x=a[k],y=WNK*a[k+step];
                a[k]=x+y,a[k+step]=x-y;WNK*=WN;
            }
        }
    }
    if(dft==-1) for(int i=0;i<Len;i++) a[i]/=Len;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("2194.in","r",stdin);
    freopen("2194.out","w",stdout);
    #endif
    n=read();
    for(int i=0;i<n;i++) a[i]=read(),b[n-i-1]=read();
    int Len=2,bit=1;
    for(;(1<<bit)<2*n-1;bit++) Len<<=1;
    Get_rev(bit);FFT(a,Len,1);FFT(b,Len,1);
    for(int i=0;i<Len;i++) a[i]*=b[i];
    FFT(a,Len,-1);
    for(int i=0;i<n;i++) printf("%d\n",(int)(a[n+i-1].real()+0.5));
    return 0;
}
posted @ 2018-07-02 21:09  XSamsara  阅读(111)  评论(0编辑  收藏  举报