BZOJ 3527 ZJOI 2014 力 FFT

題目大意

定義

求E[i] = F[i] / q[i]

思路

經過推導發現最後形成了卷積的形式,之後直接套用FFT就行了。
注意卷積捲起來之後佔用的是2倍的空間。。

CODE

#define _CRT_SECURE_NO_WARNINGS

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
using namespace std;
const double PI = acos(-1.0);

struct Complex{
    double x,y;

    Complex(double _,double __ = .0):x(_),y(__) {}
    Complex() {}
    void operator +=(const Complex &a) {
        x += a.x,y += a.y;
    }
    void operator -=(const Complex &a) {
        x -= a.x,y -= a.y;
    }
    void operator /=(double a) {
        x /= a,y /= a;
    }
    void operator *=(const Complex &a) {
        double _ = x * a.x - y * a.y,__ = x * a.y + y * a.x;
        x = _,y = __;
    }
    Complex operator +(const Complex &a)const {
        return Complex(x + a.x,y + a.y);
    }
    Complex operator -(const Complex &a)const {
        return Complex(x - a.x,y - a.y);
    }
    Complex operator /(double a)const {
        return Complex(x / a,y / a);
    }
    Complex operator *(const Complex &a)const {
        return Complex(x * a.x - y * a.y,x * a.y + y * a.x);
    }
};

inline void FFT(Complex A[],int cnt,int flag)
{
    for(int i = 0,k = 0; i < cnt; ++i) {
        if(i < k)    swap(A[i],A[k]);
        for(int j = cnt >> 1; (k ^= j) < j; j >>= 1);
    }
    Complex w,wn,t;
    for(int k = 2; k <= cnt; k <<= 1)
        for(int i = 0,j; i < cnt; i += k) {
            wn = Complex(cos(2 * PI / k),flag * sin(2 * PI / k));
            for(w = 1.0,j = 0; j < k >> 1; ++j,w *= wn) {
                t = w * A[i + j + (k >> 1)];
                A[i + j + (k >> 1)] = A[i + j] - t;
                A[i + j] += t;
            }
        }
    if(!~flag)
        for(int i = 0; i < cnt; ++i)
            A[i] /= cnt;
}

Complex A[MAX],B[MAX];

int cnt;
double src[MAX],ans[MAX];

int main()
{
    cin >> cnt;
    for(int i = 0; i < cnt; ++i)
        scanf("%lf",&src[i]);
    int l = 1;
    for(; l <= cnt << 1; l <<= 1);
    for(int i = 0; i < cnt; ++i) A[i] = Complex(src[i]);
    for(int i = 1; i < cnt; ++i) B[i] = Complex(1.0 / i / i);
    FFT(A,l,1),FFT(B,l,1);
    for(int i = 0; i < l; ++i)
        A[i] *= B[i];
    FFT(A,l,-1);
    for(int i = 0; i < cnt; ++i)
        ans[i] = A[i].x;
    reverse(src,src + cnt);
    memset(A,0,sizeof(A));
    memset(B,0,sizeof(B));
    for(int i = 0; i < cnt; ++i) A[i] = Complex(src[i]);
    for(int i = 1; i < cnt; ++i) B[i] = Complex(1.0 / i / i);
    FFT(A,l,1),FFT(B,l,1);
    for(int i = 0; i < l; ++i)
        A[i] *= B[i];
    FFT(A,l,-1);
    for(int i = 0; i < cnt; ++i)
        ans[i] -= A[cnt - i - 1].x;

    for(int i = 0; i < cnt; ++i)
        printf("%lf\n",ans[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章