【ZJOI2014】BZOJ3527力题解(FFT)

题目:BZOJ3527.
题目大意:给定一个长度为 n n n q q q数组,求:
E j = ∑ i &lt; j q i ( i − j ) 2 − ∑ i &gt; j q i ( i − j ) 2 E_j=\sum_{i&lt;j}\frac{q_i}{(i-j)^2}-\sum_{i&gt;j}\frac{q_i}{(i-j)^2} Ej=i<j(ij)2qii>j(ij)2qi

其中 1 ≤ n ≤ 1 0 5 , 1 ≤ q i &lt; 1 0 9 1\leq n\leq 10^5,1\leq q_i&lt;10^9 1n105,1qi<109.

f i = 1 i 2 f_i=\frac{1}{i^2} fi=i21,开始大力推式子:
E j = ∑ i &lt; j q i f j − i − ∑ i &gt; j q i f i − j = ∑ i = 1 j − 1 q i f j − i − ∑ i = j + 1 n q i f i − j E_j=\sum_{i&lt;j}q_if_{j-i}-\sum_{i&gt;j}q_if_{i-j}\\ =\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=j+1}^{n}q_if_{i-j} Ej=i<jqifjii>jqifij=i=1j1qifjii=j+1nqifij

p i = q n − i p_i=q_{n-i} pi=qni,那么:
E j = ∑ i = 1 j − 1 q i f j − i − ∑ i = j + 1 n p n − i f i − j = ∑ i = 1 j − 1 q i f j − i − ∑ i = 1 n − j p n − j − i f i E_j=\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=j+1}^{n}p_{n-i}f_{i-j}\\ =\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=1}^{n-j}p_{n-j-i}f_{i} Ej=i=1j1qifjii=j+1npnifij=i=1j1qifjii=1njpnjifi

发现前后两个都是卷积形式,用FFT优化即可.时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn).

代码如下:

#include<bits/stdc++.h>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=262144;
const double pi=acos(-1);

struct comp{
  double a,b;
  comp(double A=0,double B=0){a=A;b=B;}
  comp operator + (const comp &p){return comp(a+p.a,b+p.b);}
  comp operator - (const comp &p){return comp(a-p.a,b-p.b);}
  comp operator * (const comp &p){return comp(a*p.a-b*p.b,a*p.b+b*p.a);}
};

int n,m,len,rev[N+9];
comp pw[N+9],a[N+9],b[N+9],c[N+9];
double ans[N+9];

void Get_len(int n){
  int l=0;
  for (len=1;len<=n;len<<=1) ++l;
  for (int i=0;i<len;++i) rev[i]=rev[i>>1]>>1|(i&1)<<l-1; 
}

void FFT(comp *a,int n,int t){
  for (int i=0;i<n;++i)
    if (i<rev[i]) swap(a[i],a[rev[i]]);
  for (int i=1;1<<i<=n;++i){
  	int len=1<<i;
  	comp wn=comp(cos(2.0*pi/len),sin(2.0*pi/len)*(t?-1:1));
  	pw[0]=comp(1,0);
  	for (int j=1;j<len>>1;++j) pw[j]=pw[j-1]*wn;
  	for (int j=0;j<n;j+=len)
  	  for (int k=0;k<len>>1;++k){
  	  	comp x=a[j+k],y=pw[k]*a[j+k+(len>>1)];
  	  	a[j+k]=x+y;a[j+k+(len>>1)]=x-y;
  	  }
  }
}

Abigail into(){
  scanf("%d",&n);
  for (int i=1;i<=n;++i)
    scanf("%lf",&a[i].a);
}

Abigail work(){
  for (int i=0;i<=n;++i) b[i].a=a[n-i].a;
  for (int i=1;i<=n;++i) c[i].a=1.0/i/i;
  Get_len(n<<1);
  FFT(a,len,0);
  FFT(b,len,0);
  FFT(c,len,0);
  for (int i=0;i<len;++i) a[i]=a[i]*c[i],b[i]=b[i]*c[i];
  FFT(a,len,1);
  FFT(b,len,1);
  for (int i=1;i<=n;++i) ans[i]=(a[i].a-b[n-i].a)/len;
}

Abigail outo(){
  for (int i=1;i<=n;++i)
    printf("%.3lf\n",ans[i]);
  puts("");
}

int main(){
  into();
  work();
  outo();
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值