BZOJ 3527 [Zjoi2014]力 FFT

题意:链接

方法: FFT

解析:

这题比那什么 万径人踪灭 和谐多了。

BZOJ 3527 [Zjoi2014]力 FFT_第1张图片

求所有的 Ei=Fiqi

首先既然它除掉了 qi 所以我们可以直接把 qi 干掉。

然后呢观察整个的形式

如果对于一个序列

a1,a2,a3,a4,a5

代入公式则可以得到

E1=a212a322a432a542

E2=a112a322a432a542

E3=a122+a212a412a522

E4=a132+a222+a312a512

E5=a142+a232+a322+a412

发现分子与分母有规律,于是考虑构造函数。

a1x0+a2x1+a3x2+a4x3+a5x4+0x5+0x6+0x7+0x8

142x0132x1122x2112x3+0x4+112x5+122x6+132x7+142x8

将两个多项式相乘即可,取次数为n~2*n中的系数即可。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 524288
#define pi acos(-1)
using namespace std;
int n;
int rev[N];
double c[N];
struct complex
{
    double r,i;
    complex(double x=0.0,double y=0.0){r=x,i=y;}
    complex operator + (const complex a)
    {return complex(a.r+r,a.i+i);}
    complex operator - (const complex a) 
    {return complex(r-a.r,i-a.i);}
    complex operator * (const complex a)
    {return complex(r*a.r-i*a.i,r*a.i+i*a.r);}
}a[N],b[N];
void FFT(complex *a,int f)
{
    for(int i=0;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
    for(int h=2;h<=n;h<<=1)
    {
        complex wn(cos(2*pi*f/h),sin(2*pi*f/h));
        for(int i=0;i<n;i+=h)
        {
            complex w(1,0);
            for(int j=0;j<(h>>1);j++,w=w*wn)
            {
                complex t=a[i+j+(h>>1)]*w;
                a[i+j+(h>>1)]=a[i+j]-t;
                a[i+j]=a[i+j]+t;
            }
        }
    }
    if(f==-1)for(int i=0;i<n;i++)a[i].r/=n;
}
int main()
{
    scanf("%d",&n);n--;
    for(int i=0;i<=n;i++)scanf("%lf",&a[i].r);
    for(int i=0;i<n;i++)
        b[i].r=(-1.0)/((double)(n-i)*(double)(n-i));
    for(int i=n+1;i<=2*n;i++)
        b[i].r=-b[2*n-i].r;
    int m=4*n,L=0,nn=n;
    for(n=1;n<=m;n<<=1)L++;
    for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    FFT(a,1),FFT(b,1);
    for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0;i<=m;i++)c[i]=a[i].r;
    for(int i=nn;i<=2*nn;i++)printf("%lf\n",c[i]);
}

你可能感兴趣的:(fft)