P3338 [ZJOI2014]力

[E_j=dfrac{F_j}{q_j} ]

原式变成

[dfrac{sum_{i=1}^{j-1}dfrac{q_i imes q_j}{(i-j)^2}-sum_{i=j+1}^ndfrac{q_i imes q_j}{(i-j)^2}}{q_j} ]

消去 (q_j)

[sum_{i=1}^{j-1}dfrac{q_i}{(i-j)^2}-sum_{i=j+1}^ndfrac{q_i}{(i-j)^2} ]

(g_i=dfrac{1}{i^2})

[sum_{i=1}^{j-1}q_i imes g_{j-i}-sum_{i=j+1}^n q_i imes g_{i-j} ]

(g_0=q_0=0)

[sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=j}^n q_i imes g_{i-j} ]

换成差值的方式表述

[sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=0}^{n-j}q_{j+i} imes g_{i} ]

(m=n-j)(q'_i=q_{n-i})

[sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=0}^{m}q'_{m-i} imes g_{i} ]

现在均变成了卷积的形式,只要 FFT 后计算两个系数的差即可。

时间复杂度 (Oleft(nlog n ight))

code:

#include<bits/stdc++.h>
using namespace std;
#define N 262145
#define Db double
#define For(i,x,y)for(i=x;i<=(y);i++)
#define Down(i,x,y)for(i=x;i>=(y);i--)
const Db PI=acos(-1.0);
struct Complex
{
	Db x,y;
	Complex(Db X=0.0,Db Y=0.0):x(X),y(Y){};
	Complex operator+(Complex const&_)const
	{
		return Complex(x+_.x,y+_.y);
	}
	Complex operator-(Complex const&_)const
	{
		return Complex(x-_.x,y-_.y);
	}
	Complex operator*(Complex const&_)const
	{
		return Complex(x*_.x-y*_.y,x*_.y+y*_.x);
	}
}q[N],qq[N],g[N];
int tr[N];
void FFT(Complex*f,int len,bool type)
{
	int i,p,j,now;
	Complex tmp,ome,buf;
	For(i,0,len-1)
	if(i<tr[i])swap(f[i],f[tr[i]]);
	for(p=2;p<=len;p<<=1)
	{
		now=p>>1;
		ome=Complex(cos(2.0*PI/Db(p)),sin(2.0*PI/Db(p))*(type?-1.0:1.0));
		for(j=0;j<len;j+=p)
		{
			buf=Complex(1.0,0.0);
			For(i,j,j+now-1)
			{
				tmp=buf*f[i+now];
				f[i+now]=f[i]-tmp;
				f[i]=f[i]+tmp;
				buf=buf*ome;
			}
		}
	}
	if(type)
	For(i,0,len-1)f[i].x=round(f[i].x/Db(len)*1000.0)/1000.0;
}
int main()
{
	int n,m=1,i;
	scanf("%d",&n);
	For(i,1,n)
	{
		scanf("%lf",&q[i].x);
		qq[n-i].x=q[i].x;
		g[i].x=1.0/Db(i)/Db(i);
	}
	while(m<=n<<1)m<<=1;
	For(i,0,m-1)tr[i]=tr[i>>1]>>1|(i&1?m>>1:0);
	FFT(q,m,0),FFT(g,m,0),FFT(qq,m,0);
	For(i,0,m-1)q[i]=q[i]*g[i],qq[i]=qq[i]*g[i];
	FFT(q,m,1),FFT(qq,m,1);
	For(i,1,n)printf("%.3lf
",q[i].x-qq[n-i].x);
	return 0;
}

可以学到的技巧:

  • 将求和符号的起始值搞成 (0)
  • 寻找和固定的下标。
  • 找不到就尝试翻转下标,即将数组反过来。
原文地址:https://www.cnblogs.com/May-2nd/p/14163455.html