题面
给出n个数qi,给出Fj的定义如下:
令Ei=Fi/qi,求Ei.
Input
第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
n≤100000,0<qi<1000000000
Output
n行,第i行输出Ei。与标准答案误差不超过1e-2即可。
题解
有人说,这是一道快速傅里叶变换(FFT)板子题。
看到这个式子,感觉有点难,但是我们把Ei表示出来
把E拆开,
把右半边求出来,设,那么,我们发现,A已经是卷积的形式了,可以用FFT做,
把B转换一下,设B翻转过来的数组为B',q翻转过来的数组为q',那么,就可以用FFT求B了。
CODE
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 200005
#pragma GCC optimize(2)
#pragma G++ optimize(3)
#define rg register
#define DB double
using namespace std;
inline int read() {
int f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
return x * f;
}
struct Omiga{
DB a,b;
inline Omiga(){a = b = 0.0;}
inline Omiga(DB A,DB B){a = A,b = B;}
}w;
inline Omiga operator + (Omiga x,Omiga y) {
return Omiga(x.a + y.a,x.b + y.b);
}
inline Omiga operator - (Omiga x,Omiga y) {
return Omiga(x.a - y.a,x.b - y.b);
}
inline Omiga operator * (Omiga x,Omiga y) {
return Omiga(x.a*y.a - x.b*y.b,x.a*y.b + x.b*y.a);
}
inline Omiga operator / (Omiga x,DB y) {
return Omiga(x.a / y,x.b / y);
}
const DB PI = acos(-1);
int fan[MAXN*3];
inline void FFT(int len,Omiga *a,int temp) {
int ugly = log2(len);
fan[0] = 0;
for(rg int i = 1;i < len;i ++) {
fan[i] = (((fan[i>>1]>>1))|((i&1)<<(ugly-1)));
if(fan[i] < i) swap(a[fan[i]],a[i]);
}
for(rg int k = 2;k <= len;k <<= 1) {
int t = k / 2;
Omiga vw(cos(temp*PI/t)*1.0,sin(temp*PI/t)*1.0);
for(rg int i = 0;i < len;i += k) {
Omiga w2(1.0,0.0);
for(rg int j = 0;j < t;j ++,w2 = w2*vw) {
Omiga w3 = a[i + j],w4 = a[i + j + t];
a[i + j] = w3 + w4*w2;
a[i + j + t] = w3 - w4*w2;
}
}
}
if(temp == -1) for(rg int i = 0;i <= len;i ++) {
a[i] = a[i] / (DB)len;
}
return ;
}
int n,m,q,i,j,s,o,k,t;
Omiga F[MAXN*3],G[MAXN*3],AS[MAXN*3];
void juanji(Omiga *A,Omiga *B,Omiga *C,int lena,int lenb,int &lenc) {
int nm = lena + lenb;
int len = 1;
len = 1<<(int)ceil(log2(nm));
if(len==nm) len<<=1;
FFT(len,A,1);FFT(len,B,1);
for(rg int i = 0;i <= len;i ++) C[i] = A[i]*B[i];
FFT(len,C,-1);
lenc = len;
}
DB qi[MAXN];
DB ans[MAXN];
int main() {
n = read();
for(rg int i = 1;i <= n;i ++) {
scanf("%lf",&qi[i]);
}
for(rg int i = 0;i < n;i ++) F[i].a = qi[i+1],F[i].b = 0.0;
G[0].a = 0.0;G[0].b = 0.0;
for(rg int i = 1;i < n;i ++) G[i].a = 1.0 / ((DB)i*i),G[i].b = 0.0;
juanji(F,G,AS,n - 1,n - 1,m);
for(rg int i = 0;i < n;i ++) {
ans[i+1] += AS[i].a;
}
for(rg int i = 0;i <= m;i ++) F[i] = G[i] = AS[i] = w;
for(rg int i = 0;i < n;i ++) F[i].a = qi[n - i],F[i].b = 0.0;
G[0].a = 0.0;G[0].b = 0.0;
for(rg int i = 1;i < n;i ++) G[i].a = 1.0 / ((DB)i*1.0*i),G[i].b = 0.0;
juanji(F,G,AS,n - 1,n - 1,m);
for(rg int i = 1;i <= n;i ++) {
ans[i] -= AS[n - i].a;
}
for(rg int i = 1;i <= n;i ++) {
printf("%.3lf\n",ans[i]);
}
return 0;
}