BZOJ 3527: [Zjoi2014]力(FFT)

时间:2023-03-08 17:18:46
BZOJ 3527: [Zjoi2014]力(FFT)

我们看一下这个函数,很容易就把他化为 E=sigma(aj/(i-j)/(i-j))(i>j)-sigma(aj/(i-j)/(i-j))(j>i)

把它拆成两半,可以发现分子与分母下标相加总为i

也就是说,例如左边, 可以表示成g(x)= f(i)*F(x-i) (i<x) 也就是卷积了

可以轻易的构造出 f(i)= ai F(i)=1/i/i FFT就行了

右边的话,吧f(i)给倒过来就行了 (f(i)=an-i)

最后的答案 ansi=g(i)-G(n-i-1)

ok了

最近发现自己写环套树老写渣,找几道题来练练~~

CODE:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct com{ //自定义复数类
 double r,i;
 com(double real=0.0,double imag=0.0){
  r=real;i=imag;
 }
 com operator +(const com x){
  return com(x.r+r,x.i+i);
 }
 com operator -(const com x){
  return com(r-x.r,i-x.i);
 }
 com operator *(const com x){
  return com(x.r*r-x.i*i,r*x.i+i*x.r);
 }
};
#define maxn 400100 //答案的位数
#define pi acos(-1.0)
com a[maxn*2],b[maxn*2],c[maxn*2],d[maxn*2];;
bool bo[maxn*2];
int bitrec(com *x,int l){
 memset(bo,0,sizeof(bo));
 for (int i=1;i<l;i++){
  if (bo[i]) continue;
  int m=(int)log2(l)+0.5;
  int y=i,z=0;
  while (m--){
   z<<=1;
   z|=y&1;
   y>>=1;
  }
  bo[z]=bo[i]=1;
  swap(x[z],x[i]);
 }
 return 0;
}
int fft(com *x,int l,double o){
 bitrec(x,l);
 for (int i=2;i<=l;i<<=1){
  com w(cos(2.0*o*pi/i),sin(2.0*o*pi/i));
  for (int j=0;j<l;j+=i){
   com t(1.0,0.0);
   for (int k=j;k<j+(i>>1);k++){
    com u=x[k],v=x[k+(i>>1)]*t;
    x[k]=u+v;
    x[k+(i>>1)]=u-v;
    t=t*w;
   }
  }
 }
 if (o==-1) {
  for (int i=0;i<l;i++) x[i].r/=l;
 }
 return 0;
}
double x[maxn];
int main(){
 int n;
 scanf("%d",&n);int l=1;
 while (l<=n*2) l<<=1;
 for (int i=0;i<n;i++) {
  scanf("%lf",&x[i]);
  a[i]=com(x[i],0);
 }
 for (int i=n;i<l;i++) a[i]=com(0,0);
 for (int i=1;i<n;i++) b[i]=com(1.0/i/i,0);
 for (int i=n;i<l;i++) b[i]=com(0,0);
 b[0]=com(0,0);
 fft(a,l,1);
 fft(b,l,1);
 for (int i=0;i<l;i++) c[i]=a[i]*b[i];
 fft(c,l,-1);
 for (int i=0;i<n;i++) a[i]=com(x[n-i-1],0);
 for (int i=n;i<=l;i++) a[i]=com(0,0);
 fft(a,l,1);
 for (int i=0;i<l;i++) d[i]=a[i]*b[i];
 fft(d,l,-1);
 for (int i=0;i<n;i++) printf("%.3lf\n",(c[i].r-d[n-i-1].r));
 return 0;
}