【BZOJ3527】力(FFT)

题面

Description

给出n个数qi,给出Fj的定义如下:

Fj=i<jqiqj(ij)2i>jqiqj(ij)2

Ei=Fi/qi ,求 Ei .

Input

第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
n≤100000,0

Output

n行,第i行输出Ei。与标准答案误差不超过1e-2即可。

Sample Input

5

4006373.885184

15375036.435759

1717456.469144

8514941.004912

1410681.345880

Sample Output

-16838672.693

3439.793

7509018.566

4595686.886

10903040.872

题解

首先就把 qj 直接除掉
于是式子变成了
i<jqi(ij)2 另一半同理
考虑这一半
qi分别要和 112,122 等数相乘
于是做一遍FFT
系数分别为 q1,q2....qn
112,122,...
这要乘出来的系数和式子的前一半一一对应
然后把 q 反过来
变成 qn,qn1.....q1
再做一遍FFT
就是式子后面的那一边
再一一对应减去就是答案

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAX 500000
const double Pi=acos(-1);
double Q[MAX],ans[MAX];
int n;
double sqr(double x){return x*x;}
int r[MAX];
complex<double> a[MAX],b[MAX];
int N,M,l;
void FFT(complex<double> *P,int opt)
{
    for(int i=0;iif(ifor(int i=1;i1)
    {
        complex<double> W(cos(Pi/i),opt*sin(Pi/i));
        for(int p=i<<1,j=0;jcomplex<double> w(1,0);
            for(int k=0;kcomplex<double> X=P[j+k],Y=w*P[j+k+i];
                P[j+k]=X+Y;P[j+k+i]=X-Y;
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%lf",&Q[i]);

    N=M=n-1;
    for(int i=0;i<=N;++i)a[i]=Q[i+1],b[i]=1.0/sqr(i+1);
    M+=N;
    for(N=1;N<=M;N<<=1)++l;
    for(int i=0;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=2;i<=n;++i)ans[i]+=(double)(a[i-2].real()/N);

    for(int i=0;i<=N;++i)a[i].real()=b[i].real()=a[i].imag()=b[i].imag()=0;
    for(int i=0;i1.0/sqr(i+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=n-1;i;--i)ans[i]-=(double)(a[n-i-1].real()/N);

    for(int i=1;i<=n;++i)printf("%.3lf\n",ans[i]);
    return 0;
}

你可能感兴趣的:(BZOJ,各省省选,组合数学,FFT)