FFT BZOJ3527 [Zjoi2014]力
题意:给定一个公式求其值
思路:将该公式转化为卷积形式,然后用FFT求解
具体的多项式可以这样构造
q[1] q[2] q[3] q[4] ….. 0 0 0(共2*n-1项,没有q的补零)
-1/(n-1)^2 -1/(n-2)^2 …. -1/(1)^2 0 1/1^2 1/2^2 …. 1/(n-1)^2
具体的可以参考博客,里面有一个具体的例子从多项式乘法到快速傅里叶变换
// 3527 [Zjoi2014]力
//FFT 数学
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<complex>
#include<queue>
#define debug //
using namespace std;
const int maxn=100000*8+10;
typedef long long LL;
typedef complex<double> CD;
const double PI=acos(-1.0);
void BitReverse(CD a[],int n)
{
for(int i=0,j=0;i<n;i++){
if(j>i) swap(a[i],a[j]);
int k=n;
while(j&(k>>=1)) j&=~k;
j|=k;
}
}
void FFT(CD a[],int n,bool reverse)
{
BitReverse(a,n);
const double pi=reverse?PI:-PI;
for(int step=1;step<n;step<<=1){
double alpha=pi/step;
for(int k=0;k<step;k++){
CD wnk=exp(CD(0.0,alpha*k));
for(int i=k;i<n;i+=step<<1){
int j=i+step;
CD tmp=wnk*a[j];
a[j]=a[i]-tmp;
a[i]+=tmp;
}
}
}
if(reverse){
for(int i=0;i<n;i++){
a[i]/=n;
}
}
}
CD A[maxn],B[maxn];
double q[maxn];
int n;
void solve()
{
//pre init
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lf",&q[i]);
}
//after init
fill(A,A+maxn,CD(0.0,0.0));
fill(B,B+maxn,CD(0.0,0.0));
for(int i=0;i<n;i++){
A[i]=CD(q[i],0.0);
}
for(int i=0;i<n-1;i++){
double tmp=1LL*(n-i-1LL)*(n-i-1LL);
tmp=1.0/tmp;
B[i]=CD(-tmp,0.0);
B[2*n-2-i]=CD(tmp,0.0);
}
for(int i=0;i<2*n;i++){
debug("%d %0.3lf\n",i,B[i].real());
}
int tmp=n*4-3;
int len=1;
while(len<tmp) len<<=1;
FFT(A,len,false);
FFT(B,len,false);
for(int i=0;i<len;i++){
A[i]*=B[i];
}
FFT(A,len,true);
for(int i=0;i<len;i++){
debug("%0.3lf\n",A[i].real());
}
for(int i=n-1;i<2*n-1;i++){
printf("%0.3lf\n",A[i].real());
}
}
int main()
{
solve();
return 0;
}