BZOJ3527: [Zjoi2014]力 [FFT]
化简之后,发现减号左边的式子是一个卷积。右边的式子,把一个函数倒序就是卷积,分别FFT,求解答案。
大佬blog: https://blog.csdn.net/kyleyoung_ymj/article/details/51721495
#include <bits/stdc++.h>
#define pi acos(-1.0)
const int maxn = 300000+5;
using namespace std;
struct E{
double real,imag;
E(double real=0,double imag=0):real(real),imag(imag){}
friend E operator +(E A,E B){
return E(A.real+B.real,A.imag+B.imag);
}
friend E operator -(E A,E B){
return E(A.real-B.real,A.imag-B.imag);
}
friend E operator *(E A,E B){
return E(A.real*B.real-A.imag*B.imag,A.imag*B.real+A.real*B.imag);
}
};
int n,m,L,rev[maxn];
E f[maxn],rf[maxn],g[maxn],e1[maxn],e2[maxn];
void fft(E *a,int ty){
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){
E wn=E(cos(pi/i),ty*sin(pi/i));
for(int p=(i<<1),j=0;j<n;j+=p){
E w(1,0);
for(int k=0;k<i;++k,w=w*wn){
E x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
}
}
}
if(ty==-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){double x;
scanf("%lf",&x);
f[i] = x;
rf[n-i] = x;
}
for(int i=1;i<=n;++i)g[i]=1.0/i/i;//g[0]=0
m=n*2;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(rf,1);fft(g,1);
for(int i=0;i<n;++i)e1[i]=f[i]*g[i];
for(int i=0;i<n;++i)e2[i]=rf[i]*g[i];
fft(e1,-1);fft(e2,-1);
for(int i=0;i<=m/2;++i)
printf("%.3f\n",e1[i].real-e2[m/2-i].real);
}
看起来是个简单题,可是第二部分的卷积形式,推了半天都不对。。。结果直接。学的网上写法。。。然而这题想到fft,就真的简单。

浙公网安备 33010602011771号