[ZJOI2014]力

题目描述

给出n个数\(q[i]\),给出\(F[i]\)的定义如下:

\(F[i]=\sum_{j=1}^{i-1}\frac{q[i]*q[j]}{(i-j)^2}-\sum_{j=i+1}^{j=n}\frac{q[i]*q[j]}{(i-j)^2}\)

\(E[i]=\frac{F[i]}{q[i]}\),求\(E[i]\).

输入输出格式

输入格式:

第一行一个整数n。

接下来n行每行输入一个数,第i行表示qi。

输出格式:

n行,第i行输出Ei。

与标准答案误差不超过1e-2即可。

输入输出样例

输入样例#1:

5
4006373.885184
15375036.435759
1717456.469144
8514941.004912
1410681.345880

输出样例#1:

-16838672.693
3439.793
7509018.566
4595686.886
10903040.872

说明

对于30%的数据,n≤1000。

对于50%的数据,n≤60000。

对于100%的数据,n≤100000,0<qi<1000000000。


第一道FFT的题

看完题后感觉一脸懵逼

\(???\)

之后瞎化了一下然而并没有卵用

开心的看了题解

因为我们要求\(E[i]\)

\(E[i] = \frac{F[i]}{q[i]}\)

所以\(E[i] = \sum_{j=1}^{i-1}\frac{q[j]}{(i-j)^2} - \sum_{j=i+1}^{n}\frac{q[j]}{(i-j)^2}\)

然后我们设\(g[i]=\frac{1}{i^2}\)

这样\(E[i]=\sum_{j=1}^{i-1}{q[j]*g[i-j]} - \sum_{j=i+1}^{n}{q[j]*g[j-i]}\)

我们可以发现第一项满足卷积

所以第一项就直接把\(q\)\(g\)卷起来取前n项就好辣

现在考虑第二项怎么化

\(j=i+k\)

所以右边的式子就可以化成\(\sum_{k=1}^{n-i}{q[i+k]*g[k]}\)

然后我们可以把q数组翻转一下,设为\(revq[i]\)

这样式子就成了\(\sum_{k=1}^{n-i}{revq[n-i-k]*g[k]}\)

满足卷积的基本形式,我们把\(revq\)\(g\)卷起来取前n项就好辣

但是这次卷积的结果储存在n-i+1上,所以我们要从n开始反着与第一项作差

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
const int M = 400005 ;
using namespace std ;
const double Pi = acos(-1.0) ;

struct Complex {
    double x , y ;
    Complex (double Tx = 0 , double Ty = 0) { x = Tx , y = Ty ; }
}a[M] , b[M] ;
Complex operator + (Complex a , Complex b) {
    return Complex (a.x + b.x , a.y + b.y) ;
}
Complex operator - (Complex a , Complex b) {
    return Complex (a.x - b.x , a.y - b.y) ;
}
Complex operator * (Complex a , Complex b) {
    return Complex (a.x * b.x - a.y * b.y , a.x * b.y + a.y * b.x) ;
}
int n ;
int l , r[M] , digital = 1 ;
double q[M] , fir[M] , sec[M] ;
inline void FFT(Complex *A , int unit) {
    for(int i = 0 ; i < digital ; i ++)
        if(r[i] > i)
            swap(A[i] , A[r[i]]) ;
    for(int mid = 1 ; mid < digital ; (mid <<= 1)) {
        Complex W (cos(Pi / mid) , unit * sin(Pi / mid)) ;
        int R = (mid << 1) ;
        for(int j = 0 ; j < digital ; j += R) {
            Complex w (1 , 0) ;
            for(int k = 0 ; k < mid ; k ++ , w = w * W) {
                Complex x = A[j + k] , y = w * A[j + k + mid] ;
                A[j + k] = x + y ; A[j + k + mid] = x - y ;
            }
        }
    }
}
inline void Solve() {
    while(digital <= n + n) 
      digital <<= 1 , ++l ;
    for(int i = 0 ; i < digital ; i ++)
      r[i] = (r[i>>1]>>1) | ((i&1)<<(l - 1)) ;
    FFT(a , 1) ; FFT(b , 1) ;
    for(int i = 0 ; i <= digital ; i ++) a[i] = a[i] * b[i] ;
    FFT(a , -1) ;
}
int main() {
    scanf("%d",&n) ;
    for(int i = 1 ; i <= n ; i ++) scanf("%lf",&q[i]) ;
    for(int i = 1 ; i <= n ; i ++) {
        a[i].x = q[i] ;
        b[i].x = 1.0 / (1.0 * i * i) ;
    }
    Solve() ;
    for(int i = 1 ; i <= n ; i ++) fir[i] = a[i].x / ( 1.0 * digital );
    digital = 1 ; l = 0 ;
    memset(a , 0 , sizeof(a)) ; memset(b , 0 , sizeof(b)) ;
    for(int i = 1 ; i <= (n>>1) ; i ++) swap(q[i] , q[n - i + 1]) ;
    for(int i = 1 ; i <= n ; i ++) {
        a[i].x = q[i] ;
        b[i].x = 1.0/(1.0 * i * i) ;
    }
    Solve() ;
    for(int i = 1 ; i <= n ; i ++) sec[i] = a[n - i + 1].x / ( 1.0 * digital );
    for(int i = 1 ; i <= n ; i ++) printf("%.8lf\n",fir[i] - sec[i]) ;
    return 0 ;
}
posted @ 2018-08-23 07:25  beretty  阅读(211)  评论(2编辑  收藏  举报