[ZJOI2014] 力 - FFT

Description

给出 \(n\) 个数 \(q_1,q_2, \dots q_n\),定义

\[F_j~=~\sum_{i = 1}^{j - 1} \frac{q_i \times q_j}{(i - j)^2}~-~\sum_{i = j + 1}^{n} \frac{q_i \times q_j}{(i - j)^2} \]

\[E_i~=~\frac{F_i}{q_i} \]

对 \(1 \leq i \leq n\),求 \(E_i\) 的值。

Solution

转化为卷积形式 \(E_i = \sum_{j=1}^n q_j p_{i-j+n}\),其中 \(p\) 序列手工构造一下即可。

注意一下常数 \(N\) 的值要设定为 \(2\) 的整数幂。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
const int N = (1<<19); //!
#define pi acos(-1)

namespace po 
{
typedef complex<double> E;
int n,m,L;
int R[N];
E a[N],b[N];

void fft(E *a,int f)
{
	for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
	for(int i=1;i<n;i<<=1){
		E wn(cos(pi/i),f*sin(pi/i));
		for(int p=i<<1,j=0;j<n;j+=p){
			E w(1,0);
			for(int k=0;k<i;k++,w*=wn){
				E x=a[j+k],y=w*a[j+k+i];
				a[j+k]=x+y;a[j+k+i]=x-y;
			}
		}
	}
}

void mul(int _n,double *aa,double *bb,double *cc)
{
    n=_n;
    memset(a,0,sizeof a);
    memset(b,0,sizeof b);
    memset(R,0,sizeof R);
    L=0;
    m=n;
	for(int i=0,x;i<=n;i++)a[i]=aa[i];
	for(int i=0,x;i<=m;i++)b[i]=bb[i];
	m*=2;
	for(n=1;n<=m;n<<=1)L++;
	for(int i=0;i<n;i++)R[i]=(R[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);
	memset(cc,0,sizeof cc);
	for(int i=0;i<=m;i++) cc[i]=a[i].real()/n;
}
}

using po::mul;

int n;

double a[N],b[N],c[N];

signed main()
{
    ios::sync_with_stdio(false);

    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];

    for(int i=0;i<=2*n;i++)
    {
        if(i<n) b[i]=-1.0/(i-n)/(i-n);
        if(i>n) b[i]=1.0/(i-n)/(i-n);
    }

    mul(2*n+2,a,b,c);

    for(int i=0;i<n;i++)
    {
        printf("%.4lf\n",c[i+n]);
    }

    return 0;
}

上一篇:fft模板


下一篇:使用Android FFT获取声音频率