• [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
    ",fir[i] - sec[i]) ;
        return 0 ;
    }
    
  • 相关阅读:
    仿微博的JQuery日历控件
    JavaScript演示下Singleton设计模式
    简短的创建Ajax对象代码
    C++常用速查
    学习网站
    Ubuntu纯命令行安装并配置Teamviewer
    在Jupyter中使用自定义conda环境
    TensorFLow: Gradient Clipping
    Python partial 工具函数
    lambda X, y: X
  • 原文地址:https://www.cnblogs.com/beretty/p/9520635.html
Copyright © 2020-2023  润新知