码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3527 ZJOI 2014 力 FFT

时间:2015-03-04 08:32:51      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:bzoj   zjoi2014   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;
}

BZOJ 3527 ZJOI 2014 力 FFT

标签:bzoj   zjoi2014   fft   卷积   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/44055331

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!