【BZOJ3527】【FFT】力
【问题描述】
给出n个数qi,给出Fj的定义如下:
令Ei=Fi/qi。试求Ei。
【输入格式】
输入文件force.in包含一个整数n,接下来n行每行输入一个数,第i行表示qi。
【输出格式】
输出文件force.out有n行,第i行输出Ei。与标准答案误差不超过1e-2即可。
【样例输入】
5
4006373.885184
15375036.435759
1717456.469144
8514941.004912
1410681.345880
【样例输出】
-16838672.693
3439.793
7509018.566
4595686.886
10903040.872
【数据规模与约定】
对于30%的数据,n≤1000。
对于50%的数据,n≤60000。
对于100%的数据,n≤100000,0<qi<1000000000。
【分析】
这道题...在省选里面相当裸了。
自己把式子展开一下,发现跟卷积是类似的。
于是对公式的前半部分做一下FFT,后半部分再做一下FFT,减一下,然后就是公式的样子了。
感觉对FFT的理解更进一步了。
1 /* 2 宋代苏轼 3 《临江仙·夜饮东坡醒复醉》 4 夜饮东坡醒复醉,归来仿佛三更。家童鼻息已雷鸣。敲门都不应,倚杖听江声。 5 长恨此身非我有,何时忘却营营。夜阑风静縠纹平。小舟从此逝,江海寄余生。 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <cmath> 11 #include <queue> 12 #include <vector> 13 #include <iostream> 14 #include <string> 15 #include <ctime> 16 #define LOCAL 17 const double Pi = acos(-1.0); 18 const int MAXN = 100000 * 2 * 2 + 10; 19 using namespace std; 20 struct Num{ 21 double a, b; 22 Num(double x = 0, double y = 0){a = x; b = y;} 23 Num operator + (const Num &c){return Num(a + c.a, b + c.b);} 24 Num operator - (const Num &c){return Num(a - c.a, b - c.b);} 25 Num operator * (const Num &c){return Num(a * c.a - b * c.b, a * c.b + b * c.a);} 26 }x1[MAXN], x2[MAXN]; 27 double data[MAXN], Ans[MAXN]; 28 int n; 29 //交换成蝴蝶顺序 30 void change(Num *t, int len, int loglen){ 31 for (int i = 0; i < len; i++){ 32 int k = 0, x = i, tmp = loglen; 33 while (tmp--) {k = (k<<1) + (x & 1);x >>= 1;} 34 if (k < i) swap(t[k], t[i]); 35 } 36 return; 37 } 38 //0为逆向 39 void FFT(Num *x, int len, int loglen, int type){ 40 if (type) change(x, len, loglen); 41 int t;//t代表长度 42 t = (type ? 1 : (1<<loglen)); 43 for (int i = 0; i < loglen; i++){ 44 if (!type) t >>= 1; 45 int l = 0, r = l + t; 46 while (l < len){ 47 Num a, b;//临时变量 48 Num tmp(1, 0), w(cos(Pi / t), (type ? 1 : -1) * sin(Pi / t)); 49 for (int j = l; j < l + t; j++){ 50 if (type){ 51 a = x[j]; 52 b = x[j + t] * tmp; 53 x[j] = a + b; 54 x[j + t] = a - b; 55 }else{ 56 a = x[j] + x[j + t]; 57 b = (x[j] - x[j + t]) * tmp; 58 x[j] = a; 59 x[j + t] = b; 60 } 61 tmp = tmp * w; 62 } 63 l = r + t; 64 r = l + t; 65 } 66 if (type) t <<= 1; 67 } 68 if (!type){ 69 change(x, len, loglen); 70 for (int i = 0; i < len; i++) x[i].a /= len; 71 } 72 } 73 void init(){ 74 memset(x1, 0, sizeof(x1)); 75 memset(x2, 0, sizeof(x2)); 76 int len = 0; 77 while ((1 << len) < n) len++; 78 len++; 79 for (int i = 0; i < n; i++) x1[i] = Num(data[i], 0); 80 for (int i = 1; i < n; i++) x2[i] = Num((double)1.0 / (double)(i * (double)i), 0); 81 //for (int i = 1; i < n; i++) printf("%lf\n", x2[i].a); 82 83 FFT(x1, (1<<len), len, 1); 84 FFT(x2, (1<<len), len, 1); 85 for (int i = 0; i < (1 << len); i++) x1[i] = x1[i] * x2[i]; 86 FFT(x1, (1<<len), len, 0); 87 } 88 void debug(){ 89 int len = 0; 90 scanf("%d", &n); 91 while ((1<<len) <= (n << 1)) len++; 92 for (int i = 0; i < n; i++) scanf("%lf", &x1[i].a); 93 for (int i = 0; i < n; i++) scanf("%lf", &x2[i].a); 94 FFT(x1, (1<<len), len, 1); 95 FFT(x2, (1<<len), len, 1); 96 for (int i = 0; i < (1 << len); i++) x1[i] = x1[i] * x2[i]; 97 FFT(x1, (1<<len), len, 0); 98 for (int i = 0; i < n; i++) printf("%lf\n", x1[i].a); 99 } 100 101 int main() { 102 103 scanf("%d", &n); 104 for (int i = 0; i < n; i++) scanf("%lf", &data[i]); 105 init(); 106 for (int i = 0; i < n; i++) Ans[i] = x1[i].a; 107 reverse(data, data + n); 108 init(); 109 for (int i = 0; i < n; i++) Ans[i] -= x1[n - 1 - i].a; 110 for (int i = 0; i < n; i++) printf("%.3lf\n", Ans[i]); 111 //debug(); 112 return 0; 113 }