zoukankan      html  css  js  c++  java
  • P3338 [ZJOI2014]力

    [E_j=dfrac{F_j}{q_j} ]

    原式变成

    [dfrac{sum_{i=1}^{j-1}dfrac{q_i imes q_j}{(i-j)^2}-sum_{i=j+1}^ndfrac{q_i imes q_j}{(i-j)^2}}{q_j} ]

    消去 (q_j)

    [sum_{i=1}^{j-1}dfrac{q_i}{(i-j)^2}-sum_{i=j+1}^ndfrac{q_i}{(i-j)^2} ]

    (g_i=dfrac{1}{i^2})

    [sum_{i=1}^{j-1}q_i imes g_{j-i}-sum_{i=j+1}^n q_i imes g_{i-j} ]

    (g_0=q_0=0)

    [sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=j}^n q_i imes g_{i-j} ]

    换成差值的方式表述

    [sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=0}^{n-j}q_{j+i} imes g_{i} ]

    (m=n-j)(q'_i=q_{n-i})

    [sum_{i=0}^{j}q_i imes g_{j-i}-sum_{i=0}^{m}q'_{m-i} imes g_{i} ]

    现在均变成了卷积的形式,只要 FFT 后计算两个系数的差即可。

    时间复杂度 (Oleft(nlog n ight))

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 262145
    #define Db double
    #define For(i,x,y)for(i=x;i<=(y);i++)
    #define Down(i,x,y)for(i=x;i>=(y);i--)
    const Db PI=acos(-1.0);
    struct Complex
    {
    	Db x,y;
    	Complex(Db X=0.0,Db Y=0.0):x(X),y(Y){};
    	Complex operator+(Complex const&_)const
    	{
    		return Complex(x+_.x,y+_.y);
    	}
    	Complex operator-(Complex const&_)const
    	{
    		return Complex(x-_.x,y-_.y);
    	}
    	Complex operator*(Complex const&_)const
    	{
    		return Complex(x*_.x-y*_.y,x*_.y+y*_.x);
    	}
    }q[N],qq[N],g[N];
    int tr[N];
    void FFT(Complex*f,int len,bool type)
    {
    	int i,p,j,now;
    	Complex tmp,ome,buf;
    	For(i,0,len-1)
    	if(i<tr[i])swap(f[i],f[tr[i]]);
    	for(p=2;p<=len;p<<=1)
    	{
    		now=p>>1;
    		ome=Complex(cos(2.0*PI/Db(p)),sin(2.0*PI/Db(p))*(type?-1.0:1.0));
    		for(j=0;j<len;j+=p)
    		{
    			buf=Complex(1.0,0.0);
    			For(i,j,j+now-1)
    			{
    				tmp=buf*f[i+now];
    				f[i+now]=f[i]-tmp;
    				f[i]=f[i]+tmp;
    				buf=buf*ome;
    			}
    		}
    	}
    	if(type)
    	For(i,0,len-1)f[i].x=round(f[i].x/Db(len)*1000.0)/1000.0;
    }
    int main()
    {
    	int n,m=1,i;
    	scanf("%d",&n);
    	For(i,1,n)
    	{
    		scanf("%lf",&q[i].x);
    		qq[n-i].x=q[i].x;
    		g[i].x=1.0/Db(i)/Db(i);
    	}
    	while(m<=n<<1)m<<=1;
    	For(i,0,m-1)tr[i]=tr[i>>1]>>1|(i&1?m>>1:0);
    	FFT(q,m,0),FFT(g,m,0),FFT(qq,m,0);
    	For(i,0,m-1)q[i]=q[i]*g[i],qq[i]=qq[i]*g[i];
    	FFT(q,m,1),FFT(qq,m,1);
    	For(i,1,n)printf("%.3lf
    ",q[i].x-qq[n-i].x);
    	return 0;
    }
    

    可以学到的技巧:

    • 将求和符号的起始值搞成 (0)
    • 寻找和固定的下标。
    • 找不到就尝试翻转下标,即将数组反过来。
  • 相关阅读:
    linux 图形界面形式和命令行形式
    linux 配置 jdk7
    StackOverflowError
    一次失败的svchost hacking
    VB调用API的学习
    植物打僵尸休闲花园外挂代码
    中文日文翻译工具
    vb跨域访问,获得特定的frame进行处理
    HTML对象库简介(Microsoft HTML Object Library > mshtml.tlb)
    用正则分析一段vb代码含有哪些过程或者函数
  • 原文地址:https://www.cnblogs.com/May-2nd/p/14163455.html
Copyright © 2011-2022 走看看