BZOJ3527 力

来源:互联网 发布:linux常用命令手册pdf 编辑:程序博客网 时间:2024/04/30 04:15

题目简述:
我们令

Fj=i<jqiqj(ij)2i>jqiqj(ij)2
Ei=Fiqi

然后求Ei
题解:
题目的名字还真是生动形象。。
看到i<j就想到了熟悉的卷积形式
于是把两边分开求
构造俩长度为2n的
首先设:
Ai=1(ni)2(i<n)Ai=1(ni)2(i>n)
Bi=qi

然后把AB乘起来得到C,你就会发现一个奇妙的事实:
对于C的后n项,其中下标为n+i的项满足
j<i时,它加上的是AjBn+ij,这时n+ij>nBn+ij为正,而这就是前面那坨东西
同理,当j>i时,n+ij<n,Bn+ij为负,这就是后面那坨东西。
所以构造俩多项式乘一下就完了。

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef double db;const int inf=0x3f3f3f3f;const db pi=3.1415926535897932384626;int getint(){    int f=1,g=0;char c=getchar();    while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar();    return f*g;}const int maxn=1000005;struct comp{    db re,im;    comp(){}    comp(db re,db im):re(re),im(im){}    comp operator + (const comp &poi)const {return comp(re+poi.re,im+poi.im);}    comp operator - (const comp &poi)const {return comp(re-poi.re,im-poi.im);}    comp operator * (const comp &poi)const {return comp(re*poi.re-im*poi.im,re*poi.im+im*poi.re);}};int rev[maxn];int n;db q[maxn];int len;comp a[maxn],b[maxn],c[maxn];void fft(comp *a,int n,db f){    for(int i=0;i<n;i++)    {        if(i>rev[i])        {            swap(a[i],a[rev[i]]);        }    }    comp w,wn,temp1,temp2;    int mid;    for(int i=2;i<=n;i<<=1)    {        wn=comp(cos(2.0*pi/i*f),sin(2.0*pi/i*f));        mid=i>>1;        for(int j=0;j<n;j+=i)        {            w=comp(1.0,0);            for(int k=0;k<mid;k++)            {                temp1=a[j+k];                temp2=a[j+k+mid]*w;                a[j+k]=temp1+temp2;                a[j+k+mid]=temp1-temp2;                w=w*wn;            }        }    }    if(f==-1)    {        for(int i=0;i<n;i++)        {            a[i].re/=n;        }    }}db sqr(db x){return x*x;}int main(){//  freopen("in.txt","r",stdin);    n=getint();    for(int i=0;i<n;i++)    {        scanf("%lf",&a[i].re);    }       int tn=n;    for(int i=0;i<tn;i++)    {        b[i].re=-(1.0/sqr(n-i));    }    for(int i=tn+1;i<=tn*2;i++)    {        b[i].re=1.0/sqr(i-n);    }    int m=1;    len=0;    n=n*2+1;    while(m<n)m<<=1,len++;    n=m;    for(int i=0;i<n;i++)    {        int temp=i;        int pos=0;        for(int j=1;j<=len;j++)        {            pos<<=1;pos|=temp&1;temp>>=1;        }        rev[i]=pos;    }    fft(a,n,1);    fft(b,n,1);    for(int i=0;i<n;i++)    {        c[i]=a[i]*b[i];    }       fft(c,n,-1);    for(int i=0;i<tn;i++)    {        printf("%lf\n",c[i+tn].re);    }    return 0;}
0 0
原创粉丝点击