zoukankan      html  css  js  c++  java
  • 洛谷P3338 [ZJOI2014]力(FFT)

    传送门

    题目要求$$E_i=frac{F_i}{q_i}=sum_{j=1}^{i-1}frac{q_j}{(i-j)^2}-sum_{j=i+1}^nfrac{q_j}{(j-i)^2}$$

    令$x_i=frac{1}{i^2}$,则有$$E_i=sum_{j=1}^{i-1} q_j x_{i-j}-sum_{j=i+1}^n q_j x_{j-i}$$

    令$p_i=q_{n-i+1}$,则有$$E_i=sum_{j=1}^{i-1} q_j x_{i-j}-sum_{j=i+1}^n p_{n-j+1} x_{j-i}$$

    那么不难发现这两个都是卷积(然而我连卷积是啥都不知道)

    简单来讲,两个多项式的卷积$(f*g)(n)=sum_{i=0}^nf(i)g(n-i)$,可以发现这个和多项式乘法的某一项系数的值的求法相同

    然后只要用FFT求出两个卷积,然后做差就可以了

     1 //minamoto
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=3e5+5;const double Pi=acos(-1);
     7 struct complex{
     8     double x,y;
     9     complex(double xx=0,double yy=0){x=xx,y=yy;}
    10     inline complex operator +(complex b){return complex(x+b.x,y+b.y);}
    11     inline complex operator -(complex b){return complex(x-b.x,y-b.y);}
    12     inline complex operator *(complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
    13 }A[N],B[N],C[N];
    14 int n,m,l,r[N],limit=1;
    15 void FFT(complex *A,int type){
    16     for(int i=0;i<limit;++i)
    17     if(i<r[i]) swap(A[i],A[r[i]]);
    18     for(int mid=1;mid<limit;mid<<=1){
    19         complex Wn(cos(Pi/mid),type*sin(Pi/mid));
    20         for(int R=mid<<1,j=0;j<limit;j+=R){
    21             complex w(1,0);
    22             for(int k=0;k<mid;++k,w=w*Wn){
    23                 complex x=A[j+k],y=w*A[j+mid+k];
    24                 A[j+k]=x+y,A[j+mid+k]=x-y;
    25             }
    26         }
    27     }
    28 }
    29 int main(){
    30 //    freopen("testdata.in","r",stdin);
    31     scanf("%d",&n);
    32     while(limit<=n*2) limit<<=1,++l;
    33     for(int i=0;i<=limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    34     for(int i=1;i<=n;++i)
    35     scanf("%lf",&A[i].x),B[n+1-i].x=A[i].x,C[i].x=1.0/i/i;
    36     FFT(A,1),FFT(B,1),FFT(C,1);
    37     for(int i=0;i<=limit;++i) A[i]=A[i]*C[i],B[i]=B[i]*C[i];
    38     FFT(A,-1),FFT(B,-1);
    39     for(int i=0;i<=limit;++i) A[i].x/=limit,B[i].x/=limit;
    40     for(int i=1;i<=n;++i)
    41     printf("%.3lf
    ",A[i].x-B[n-i+1].x);
    42     return 0;
    43 }
  • 相关阅读:
    Confluence 6 连接到一个 LDAP 目录
    Confluence 6 LDAP 成员结构设置
    Confluence 6 LDAP 用户组结构设置
    Confluence 6 LDAP 用户结构设置
    Confluence 6 LDAP 高级设置
    Confluence 6 自动添加用户到用户组
    Confluence 6 权限设置
    一个小白的测试环境docker化之路
    客户端SDK测试思路
    限时购校验小工具&dubbo异步调用实现限
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9742771.html
Copyright © 2011-2022 走看看