[bzoj3527][Zjoi2014]力【FFT】

【题目描述】

Description

给出n个数qi,给出Fj的定义如下:
令Ei=Fi/qi,求Ei.

Input

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

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

HINT

Source

【题解】

    Ei= ∑ qj / (i-j)^2 (i<j) - ∑ qj / (i-j)^2 (i>j)

    构造多项式A=q1*x+q2*x^2+...+qn*x^n;

                     B=-1/(n-1)^2 *x+-1/(n-2)^2 * x^2 +...+ 0 * x^n +... + 1/(n-1)^2 * x^(2n-1)

      将A卷上B,第n+i项的系数为第Ei的答案。

   

/* --------------
    user Vanisher
    problem bzoj-3527 
----------------*/
# include <bits/stdc++.h>
# define 	N 		1010000
# define 	ll 		long long
using namespace std;
double pi=acos(-1.0);
int read(){
	int tmp=0, fh=1; char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
	return tmp*fh;
}
struct number{
	double x,y;
}a[N],b[N];
number operator +(number x, number y){return (number){x.x+y.x,x.y+y.y};}
number operator -(number x, number y){return (number){x.x-y.x,x.y-y.y};}
number operator *(number x, number y){return (number){x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x};}
double sqr(double x){return x*x;}
int n;
void FFT(number *a, int n, int tag){
	for (int i=0,j=0; i<n; i++){
		if (i<j) swap(a[i],a[j]);
		for (int k=n/2; k>0; k>>=1)
			if ((j&k)!=0) j=j-k;
				else {
					j=j+k;
					break;
				}
	}
	for (int i=2; i<=n; i<<=1){
		number w={cos(2*pi/i),sin(2*pi/i*tag)};
		for(int j=0; j<n; j+=i){
			number wn={1,0};
			for (int k=j; k<j+i/2; k++,wn=wn*w){
				number x=a[k], y=a[k+i/2]*wn;
				a[k]=x+y; a[k+i/2]=x-y;
			}
		} 
	}
	if (tag==-1) for (int i=0; i<n; i++) a[i].x=a[i].x/n;
}
int main(){
	n=read();
	for (int i=1; i<=n; i++)
		scanf("%lf",&a[i].x);
	for (int i=1; i<n; i++){
		b[i].x=-1.0/sqr(n-i);
		b[n+n-i].x=1.0/sqr(n-i);
	}
	int nn=1;
	while (nn<=n*2) nn<<=1;
	FFT(a,nn,1); FFT(b,nn,1);
	for (int i=0; i<nn; i++)
		a[i]=a[i]*b[i];
	FFT(a,nn,-1);
	for (int i=n+1; i<=n+n; i++)
		printf("%.3lf\n",a[i].x);
	return 0;
}

posted @ 2018-02-12 22:00  Vanisher  阅读(97)  评论(0编辑  收藏  举报