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

10903040.872

题解

卷积什么的感觉好优美~~

卷积

先普及一下离散卷积的定义【瞎编的】:

对于两个序列\(x(n)\)和\(y(n)\)

其卷积\((x*y)(n) = \sum_{-\infty}^{\infty}x(k)y(n - k)\)

即当一个序列所有i位置上的值c(i)等于所有位置之和为i的x(k)*y(i - k)乘积的和时,可以看做c()为x()和y()的卷积

就好比多项式a(n) b(n)相乘,对于次数i的系数\(c(i)=\sum a(k)*b(i - k)\)

而求离散卷积可以使用离散快速傅里叶\(O(nlogn)\)高效求出

本题

观察式子

\(Ei = \sum_{j<i}\frac{qj}{(i-j)^2} - \sum_{j>i}\frac{qj}{(i-j)^2}\)

我们将两个求和分开来求

我们令\(b(i) = \frac{1}{i^2}\),特别的,\(b(0) = 0\)

我们令\(a(i) = qi\)

我们会发现左边【即为\(L(i)\)】\(L(i) = \sum a(j)*b(i - j)\),刚好就是卷积的形式

可以用fft求出

同样的,对于右边

\(R(i) = \sum a(j)*b(j - i)\)

诶?不对啊,\(j + j - i\)不是定值啊。

但是ta们的位置关系还是很固定,考虑变形

我们将\(a(i)\)翻转,即令\(c(n-i)=a(i)\)

奇迹发生了:

\(R(i) = \sum c(n - j)*b(j - i)\)

这样我们算出的卷积,\(R(i)\)就与\(E_{n-i}\)对应

最后将算出的两个结果相减

呼啦啦,搞完啦~~

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<complex>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<‘ ‘; puts("");
using namespace std;
const int maxn = 400005,maxm = 100005,INF = 1000000000;
const double pi = acos(-1);
typedef complex<double> E;
E a[maxn],b[maxn],aa[maxn];
int n,m,L,R[maxn];
void fft(E* a,int f){
    for (int i = 0; i < n; i++) if (i < R[i]) swap(a[i],a[R[i]]);
    for (int i = 1; i < n; i <<= 1){
        E wn(cos(pi / i),f * sin(pi / i));
        for (int j = 0; j < n; j += (i << 1)){
            E w(1,0);
            for (int k = 0; k < i; k++,w *= wn){
                E x = a[j + k],y = w * a[j + k + i];
                a[j + k] = x + y; a[j + k + i] = x - y;
            }
        }
    }
    if (f == -1) for (int i = 0; i < n; i++) a[i] /= n;
}
int main(){
    scanf("%d",&n); --n; double q;
    for (int i = 0; i <= n; i++){
        scanf("%lf",&q);
        a[i] = q; aa[n - i] = q;
    }
    for (int i = 1; i <= n; i++) b[i] = 1.0 / i / i;
    m = n << 1; for (n = 1; n <= m; n <<= 1) L++;
    for (int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
    fft(a,1); fft(aa,1); fft(b,1);
    for (int i = 0; i < n; i++) a[i] *= b[i];
    for (int i = 0; i < n; i++) aa[i] *= b[i];
    fft(a,-1); fft(aa,-1);
    for (int i = 0; i <= (m >> 1); i++) printf("%.6lf\n",a[i].real() - aa[(m >> 1) - i].real());
    return 0;
}

原文地址:https://www.cnblogs.com/Mychael/p/8352623.html

时间: 2024-11-08 16:52:29

BZOJ3527 [Zjoi2014]力 【fft】的相关文章

[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

[Zjoi2014]力(FFT/NTT)

[Zjoi2014]力(FFT,卷积) 题意:给定\(n\)个点电荷,排在单位数轴上,求每个点的场强 考虑每个\(i\)对于每个\(j\)的贡献,分析式子 \(E=\cfrac{q_i}{(j-i)^2}\) 令\(f(x)=\sum q_ix^i\) \(g(x)=\sum a_ix^i,a_i=i<0?-\frac{1}{i^2}:\frac{1}{i^2}\) \(g(x)\)每一项\(x\)的指数其实是\(j-i\)的值 求\(f(x)\cdot g(x)\)即可,注意负数系数的话偏移一

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

BZOJ 3527: [Zjoi2014]力 FFT

3527: [Zjoi2014]力 Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<1000000000 Output n行,第i行输出Ei.与标准答案误差不超过1e-2即可. Sample Input 5 4006373.885184 15375036.435759 1717456.469144 8514941.004912 1410681.34

【BZOJ】3527: [Zjoi2014]力 FFT

[参考]「ZJOI2014」力 - FFT by menci [算法]FFT处理卷积 [题解]将式子代入后,化为Ej=Aj-Bj. Aj=Σqi*[1/(i-j)^2],i=1~j-1. 令f(i)=qi,g(i)=1/i^2,定义f(0)=g(0)=0(方便卷积). Aj=Σf(i)*g(j-i),i=0~j-1,标准的卷积形式. 而对于Bj,将g反转后就是和为i+n-1的标准卷积形式了. 第一次FFT后,记得对a数组后半部分清零后再进行第二次FFT. 复杂度O(n log n). #incl

【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

bzoj3527: [Zjoi2014]力 卷积+FFT

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

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

P3338 [ZJOI2014]力 /// FFT 公式转化翻转

题目大意: https://www.luogu.org/problemnew/show/P3338 题解 #include <bits/stdc++.h> #define N 300005 #define PI acos(-1.0) using namespace std; struct cpx { double x,y; cpx (double a=0.0,double b=0.0) { x=a; y=b; } cpx operator - (const cpx &b)const {