力「ZJOI2014」

题意

给出数列(q)以及(F_j)的定义:

(F_j=sum_{i<j} frac{q_iq_j}{(i-j)^2}-sum_{j<i} frac{q_iq_j}{(i-j)^2})

(E_i=frac{F_i}{q_i}),求(E_i)


思路

准确的说我们要求(E_j)

带入式子得到(E_j=sum{i<j}frac{q_i}{(i-j)^2}-sum_{j<i}frac{q_i}{(i-j)^2})

那么就是(E_j=sum^{j-1}_{i=1}frac{q_i}{(i-j)^2}-sum^n_{i=j+1}frac{q_i}{(i-j)^2})

(f(i)=q_i, g(i)=frac{1}{i^2})

带入得到(E_j=sum^{j-1}_{i=1}f(i)g(j-i)-sum^n_{i=j+1}f(i)g(j-i)=sum^{j-1}_{i=1}f(i)g(j-i)-sum^{n-j}_{i=1}f(i-j)g(-i))

前者卷积,后者翻转之后卷积。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {
	
	template<typename T> inline void read (T &x) {
		x=0;T f=1;char c=getchar();
		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
		x*=f;
	}
	template<typename T> inline void write (T x) {
		if (x<0) putchar('-'),x=-x;
		if (x>=10) write(x/10);
		putchar(x%10+'0');
	}
	
} 

using namespace StandardIO;

namespace Solve {
	
	const int N=600000;
	const double pi=acos(-1);
	typedef complex<double> cx;
	
	int n,m,L;
	cx a[N],b[N];
	int R[N];
	double x;
	
	inline void fft (cx *tmp,int type) {
		for (register int i=0; i<n; ++i) if (i<R[i]) swap(tmp[i],tmp[R[i]]);
		for (register int i=1; i<n; i<<=1) {
			cx wn(cos(pi/i),type*sin(pi/i));
			for (register int j=0; j<n; j+=(i<<1)) {
				cx w(1,0);
				for (register int k=0; k<i; ++k,w*=wn) {
					cx s=tmp[j+k],t=tmp[j+k+i]*w;
					tmp[j+k]=s+t,tmp[j+k+i]=s-t;
				}
			}
		}
	}
	
	inline void MAIN () {
		read(n);
		for (register int i=0; i<n; ++i) scanf("%lf",&x),a[i]=x;
		for (register int i=0; i<n; ++i) b[i]=-1.0/(static_cast<double>(n-i)*(n-i));
		for (register int i=n+1; i<=2*n; ++i) b[i]=1.0/(static_cast<double>(i-n)*(i-n));
		m=2*n;
		for (n=1; n<=m; n<<=1) ++L;
		for (register int i=0; i<n; ++i) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
		fft(a,1),fft(b,1);
		for (register int i=0; i<n; ++i) a[i]*=b[i];
		fft(a,-1);
		for (register int i=m/2; i<=m-1; ++i) printf("%.3lf
",a[i].real()/n);
	}
	
}

int main () {
	Solve::MAIN();
}
原文地址:https://www.cnblogs.com/ilverene/p/11425956.html