Description
给出n个数qi,给出Fj的定义如下:
令Ei=Fi/qi,求Ei.
Input
第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
n≤100000,0
<
<script type="math/tex" id="MathJax-Element-1"><</script>qi
<
<script type="math/tex" id="MathJax-Element-2"><</script>1000000000
Output
n行,第i行输出Ei。与标准答案误差不超过1e-2即可。
Sample Input
5
4006373.885184
15375036.435759
1717456.469144
8514941.004912
1410681.345880
Sample Output
-16838672.693
3439.793
7509018.566
4595686.886
10903040.872
Solution
复习一下FFT的板子。
曾经有一道裸着的FFT出现在我面前,可是我没好好珍惜。。
众所周知,FFT是拿来加速卷积的。所谓的卷积,就是形如 ∑ij=0f(j)∗g(i−j) 的式子。
我们对于一个
i
可以
经过观察可以发现,卷积都具有 j+(i−j)=i 的和一定的形式,对于 (i+j)−j=i 的差一定的形式,可以将前一个多项式反过来,就变成了和一定的卷积形式。
这题直接将柿子画一下,减号前面是个和一定的卷积,减号后面差一定反过来卷即可。
时间复杂度:O(FFT)。
Code
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#define MAXN 100100
using namespace std;
const double PI = acos(-1.0);
int n, nn;
struct Complex{
double real, image;
Complex() {}
Complex(double _real, double _image){
real = _real; image = _image;
}
friend Complex operator + (Complex A, Complex B){
return Complex(A.real + B.real, A.image + B.image);
}
friend Complex operator - (Complex A, Complex B){
return Complex(A.real - B.real, A.image - B.image);
}
friend Complex operator * (Complex A, Complex B){
return Complex(A.real * B.real - A.image * B.image, A.real * B.image + A.image * B.real);
}
}f[MAXN<<2], g[MAXN<<2], ff[MAXN<<2], e1[MAXN<<2], e2[MAXN<<2];
void Reverse(Complex *A){
for(int i = 0; i < nn-1; i++){
int j = 0;
for(int k = 1, tmp = i; k < nn; k <<= 1, tmp >>= 1)
j = ((j << 1) | (tmp & 1));
if(j > i) swap(A[i], A[j]);
}
}
void FFT(Complex *A, int DFT){
Reverse(A);
for(int s = 1; (1<<s) <= nn; s++){
int m = 1 << s;
Complex wm = Complex(cos(PI*2*DFT/m), sin(PI*2*DFT/m));
for(int k = 0; k < nn; k += m){
Complex w = Complex(1, 0);
for(int j = 0; j < (m>>1); j++){
Complex u = A[k+j], t = w * A[k+j+(m>>1)];
A[k+j] = u + t;
A[k+j+(m>>1)] = u - t;
w = w * wm;
}
}
}
if(DFT == -1) for(int i = 0; i < nn; i++) A[i].real /= nn, A[i].image /= nn;
}
int Deg(int x){
int t = 1;
while(t < x) t <<= 1;
return t;
}
int main(){
scanf("%d", &n);
nn = Deg(n) << 1;
for(int i = 0; i < n; i++){
scanf("%lf", &f[i].real);
f[i].image = 0.0;
ff[n-i-1] = f[i];
}
for(int i = n; i < nn; i++) f[i] = ff[i] = Complex(0, 0);
for(int i = 0; i < n; i++){
if(!i) g[i].real = 0.0;
else g[i].real = 1.0 / i / i;
g[i].image = 0.0;
}
for(int i = n; i < nn; i++) g[i] = Complex(0, 0);
FFT(f, 1);
FFT(g, 1);
FFT(ff, 1);
for(int i = 0; i < nn; i++) e1[i] = f[i] * g[i], e2[i] = ff[i] * g[i];
FFT(e1, -1);
FFT(e2, -1);
for(int i = 0; i < n; i++)
printf("%.3lf\n", e1[i].real - e2[n-i-1].real);
return 0;
}
有空记得填NTT这个坑=。=