BZOJ3527: [Zjoi2014]力

9 篇文章 0 订阅
3 篇文章 0 订阅

题目大意: Fj=i<jqiqj(ij)2i>jqiqj(ij)2
Ei=Fi/qi ,求出所有的 Ei

首先可以把 qj 消掉,变成 Ej=i<jqi(ij)2i>jqi(ij)2
我们可以想象 F(x)=qx,G(x)=1x2
这样前后两项就都可以化成卷积的形式,然后就可以直接FFT了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 400010
using namespace std;
const double pi=acos(-1);
struct E{double s,x;};
E operator-(const E&x,const E&y){return (E){x.s-y.s,x.x-y.x};}
E operator+(const E&x,const E&y){return (E){x.s+y.s,x.x+y.x};}
E operator*(const E&x,const E&y){return (E){x.s*y.s-x.x*y.x,x.s*y.x+x.x*y.s};}
E omg[N];
void FFT(E *A,E *B,int s,int le,int t)
{
    if(le==1){B[s]=A[s];return;}
    int l=le/2,i;
    for(i=0;i<l;i++)
    B[s+i]=A[s+2*i],B[s+l+i]=A[s+2*i+1];
    FFT(B,A,s,l,t*2);
    FFT(B,A,s+l,l,t*2);
    for(i=0;i<l;i++)
    {
        B[s+i]=A[s+i]+omg[i*t]*A[s+i+l];
        B[s+l+i]=A[s+i]-omg[i*t]*A[s+i+l];
    }
}
E ffta[N],fftb[N],fftc[N];
void AFFT(double *A,double *B,double *C,int n)
{
    int i=1;
    while(i<n) i*=2;
    n=2*i;
    for(i=0;i<=n;i++)
    {
        ffta[i]=(E){A[i],0};
        fftb[i]=(E){B[i],0};
        omg[i]=(E){cos(pi*2*i/n),sin(pi*2*i/n)};
    }
    FFT(ffta,fftc,0,n,1);
    FFT(fftb,ffta,0,n,1);
    for(i=0;i<n;i++)
    fftb[i]=ffta[i]*fftc[i];
    for(i=0;i<=n;i++)
    omg[i]=(E){cos(-pi*2*i/n),sin(-pi*2*i/n)};
    FFT(fftb,fftc,0,n,1);
    for(i=0;i<n;i++)
    C[i]=fftc[i].s/n;
}
double q[N],s1[N],s2[N],g[N];
int main()
{
    int n;
    scanf("%d",&n);
    int i,j;
    for(i=0;i<n;i++)
    scanf("%lf",&q[i]);
    for(i=1;i<n;i++)
    g[i]=1.0/i/i;
    AFFT(q,g,s1,n);
    for(i=0;i<n/2;i++)
    swap(q[i],q[n-1-i]);
    AFFT(q,g,s2,n);
    for(i=0;i<n;i++)
    printf("%.8lf\n",s1[i]-s2[n-1-i]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值