BZOJ3527: [Zjoi2014]力

3527: [Zjoi2014]力

Time Limit: 30 Sec  Memory Limit: 256 MBSec  Special Judge
Submit: 2350  Solved: 1394
[Submit][Status][Discuss]

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
思路{
  我们转化一下模型.问题转化为有一列排成直线的点电荷,求每个点所在复合电场的场强.Interesting....
  
  好吧,我在瞎BB...
  在写这道题之前一直以为$FFT$只能搞简单的多项式乘法.
  没注意其真正用意是快速求卷积.....所以这个题就G啦....
  哈哈哈,原来这就是一道卷积板子题啊....
  首先场强直接干翻一个$Q_i$,再单独考虑一半式子.
  对点电荷i, $Ans=\sum_{j=1}^{i-1}{Q_j/(i-j)^2}$    $i$ 和 $i-j$ 构成卷积形式.
  直接构造$F(i)=Q_i,G(i)=1/i^2$ 那么就是求卷积$H(x)=\sum_{h=1}^{x-1}{F(x)*G(h-x)}$,上$FFT$咯
  对于后一半式子,把它翻转过来就可以了.
}
#include<bits/stdc++.h>
#define RG register
#define il inline
#define db double
#define LL long long
#define N 1000000
using namespace std;
typedef complex<db>W;
const db pi=acos(-1);
W f[N],F[N],G[N];
int rev[N],n,L;
void FFT(W * A,int f){
  for(int i=0;i<n;++i)if(i>rev[i])swap(A[i],A[rev[i]]);
  for(int i=1;i<n;i<<=1){
    W wn(cos(pi/i),sin(f*pi/i)),x,y;
    for(int j=0;j<n;j+=(i<<1)){
      W w(1,0);
      for(int k=0;k<i;k++,w*=wn){
    x=A[j+k],y=w*A[j+k+i];
    A[j+k]=x+y;
    A[j+k+i]=x-y;
      }
    }
  }
  if(f==-1)for(int i=0;i<n;++i)A[i].real()/=n;
}
int main(){
  scanf("%d",&n);n--;
  for(int i=0;i<=n;++i){
    db x;
    scanf("%lf",&x);
    f[i]=F[n-i]=x;
  }
  int m=2*n;
  for(LL i=1;i<=n;++i)G[i]=(1.0/(i*i));
  for(n=1;n<=m;n<<=1)L++;
  for(int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
  FFT(f,1),FFT(G,1);FFT(F,1);
  for(int i=0;i<n;++i)f[i]*=G[i];
  for(int i=0;i<n;++i)F[i]*=G[i];
  FFT(f,-1);FFT(F,-1);
  for(int i=0;i<=m/2;++i)printf("%.3lf\n",(f[i].real()-F[(m/2)-i].real()));
  return 0;
}

 

posted @ 2017-09-07 23:51  QYP_2002  阅读(180)  评论(0编辑  收藏  举报