【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 }

时间: 2024-09-30 20:09:31

【BZOJ3527】【FFT】力的相关文章

【BZOJ-3527】力 FFT

3527: [Zjoi2014]力 Time Limit: 30 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1544  Solved: 899[Submit][Status][Discuss] Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<1000000000 Output n行,第i行

BZOJ3527 [Zjoi2014]力 【fft】

题目 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. 输入格式 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. 输出格式 n行,第i行输出Ei.与标准答案误差不超过1e-2即可. 输入样例 5 4006373.885184 15375036.435759 1717456.469144 8514941.004912 1410681.345880 输出样例 -16838672.693 3439.793 7509018.566 4595686.886 1090304

bzoj3527: [Zjoi2014]力 卷积+FFT

先写个简要题解:本来去桂林前就想速成一下FFT的,结果一直没有速成成功,然后这几天断断续续看了下,感觉可以写一个简单一点的题了,于是就拿这个题来写,之前式子看着别人的题解都不太推的对,然后早上6点多推了一个多小时终于发现了一个很巧妙的方法,首先问题的关键在于后半个式子,因为显然前半个式子很容易想到卷积的形式,那么直接FFT就好了,但是后半部分不好考虑,一般肯定是通过类似换元的做法得出结论,所以到中间有一步就有点难度,那个地方我一直卡.后来突然想到,既然前半部分i<j时那么好处理,那么i>j的情

BZOJ3527[ZJOI]力

无题面神题 原题意: 求所有的Ei=Fi/qi. 题解: qi被除掉了,则原式中的qj可以忽略. 用a[i]表示q[i],用b[j-i]来表示±1/((j-i)^2)(j>i时为正,j<i时为负) 则求E[j]就是多项式乘法了. 因为是FFT,所以b的下标要增加到0及以上. 这题时限有30s,比某题友好多了. 代码: type xs=record x,y:double; end; arr=array[0..1000000]of xs; var e,t:arr; a:array[1..5]of

bzoj3527: [Zjoi2014]力

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 const int maxn=400005; 8 const double PI=acos(-1); 9 struct node{ 10 double real,imag; 11 void

关于万恶的多项式

模板: 1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include&l

[复习]多项式和生成函数相关内容

[复习]多项式和生成函数相关内容 多项式 涉及的方面 主要在于多项式的乘法,也就是\(FFT,NTT,MTT\). 但是也多项式的求逆,\(exp\),\(ln\),开根,求导,积分等操作. 多项式乘法 并没有什么好复习的,记好板子就行了.同样也是多项式运算的基础. 泰勒展开&麦克劳林级数 泰勒展开: 如果\(f(x)\)在\(x0\)处存在\(n\)阶导,那么就有: \[\begin{aligned}f(x)&=f(x0)+\frac{f^1(x0)}{1!}(x-x0)+\frac{f

【bzoj3527】[Zjoi2014]力 FFT

2016-06-01  21:36:44 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3527 我就是一个大傻叉 微笑脸 1 #include<bits/stdc++.h> 2 #define inf 1000000000 3 #define ll long long 4 #define N 500005 5 using namespace std; 6 int read(){ 7 int x=0,f=1;char ch=getchar

[Zjoi2014]力 FFT

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; typedef double dd; const dd pi=acos(0.0)*2; #define N 400005 struct P{ dd x,y; P(dd A=0.0,dd B=0.0){ x=A; y=B; } P