BZOJ 3527 力

题目:
B Z O J 3527 BZOJ3527 BZOJ3527

给定数组 q q q,长度为 n n n,数组 F F F按以下公式求出
F i = ∑ j < i q i q j ( i − j ) 2 − ∑ j > i q i q j ( i − j ) 2 F_i=\sum_{j<i}\frac{q_iq_j}{(i-j)^2}-\sum_{j>i}\frac{q_iq_j}{(i-j)^2} Fi=j<i(ij)2qiqjj>i(ij)2qiqj
请你求出数组 E E E E i = F i q i E_i=\frac{F_i}{q_i} Ei=qiFi n ≤ 1 0 5 n\le 10^5 n105

思路:
f ( i ) = 1 i 2 f(i)=\frac{1}{i^2} f(i)=i21
E i = ∑ j = 0 i − 1 q j f i − j − ∑ j = i + 1 n − 1 q j f j − i = ∑ j = 0 i q j f i − j − ∑ j = i n − 1 q j f j − i \begin{aligned} E_i&=\sum_{j=0}^{i-1}q_jf_{i-j}-\sum_{j=i+1}^{n-1}q_jf_{j-i}\\ &=\sum_{j=0}^{i}q_jf_{i-j}-\sum_{j=i}^{n-1}q_jf_{j-i}\\ \end{aligned} Ei=j=0i1qjfijj=i+1n1qjfji=j=0iqjfijj=in1qjfji
可以定义 f 0 = 0 f_0=0 f0=0,然后把 q j q_j qj映射到 Q n − 1 − j Q_{n-1-j} Qn1j。则前面的就是卷积,可以用 F F T FFT FFT算,系数就是数组 q , f q,f q,f,取第 i i i项。对于后面的式子有
∑ j = i n − 1 Q n − 1 − j f j − i 令 t = j − i = ∑ t = 0 n − 1 − i Q n − 1 − t − i f t \begin{aligned} &\sum_{j=i}^{n-1}Q_{n-1-j}f_{j-i}\quad 令t=j-i\\ =&\sum_{t=0}^{n-1-i}Q_{n-1-t-i}f_{t}\\ \end{aligned} =j=in1Qn1jfjit=jit=0n1iQn1tift
然后也可以用卷积算,注意系数是数组 Q , f Q,f Q,f,而且取第 n − 1 − i n-1-i n1i项。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double Pi=acos(-1.0);
const int N=300009;
struct com
{
    double x,y;
    com(double xx=0,double yy=0)
    {
        x=xx,y=yy;
    }
}a[N],aa[N],b[N],c[N],cc[N];
com operator + (com a,com b)
{
    return com(a.x+b.x,a.y+b.y);
}
com operator - (com a,com b)
{
    return com(a.x-b.x,a.y-b.y);
}
com operator * (com a,com b)
{
    return com(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
int n,m,bit=0,lim=1,r[N];
double sinn[N],coss[N];
void init()
{
    while(lim<=2*n-1)
        lim<<=1,bit++;
    for(int i=1;i<lim;i<<=1)
        sinn[i]=sin(Pi/i),coss[i]=cos(Pi/i);
    for(int i=0;i<lim;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(com *a,int type)
{
    for(int i=0;i<lim;i++)
        if(i<r[i])
        swap(a[i],a[r[i]]);
    for(int mid=1;mid<lim;mid<<=1)
    {
        com W(coss[mid],type*sinn[mid]);
        for(int r=mid<<1,j=0;j<lim;j+=r)
        {
            com e(1,0);
            for(int k=0;k<mid;k++,e=e*W)
            {
                com x=a[j+k],y=e*a[j+k+mid];
                a[j+k]=x+y,a[j+k+mid]=x-y;
            }
        }
    }
    if(type==-1)
        for(int i=0;i<lim;i++)
            a[i].x/=lim;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lf",&a[i].x),aa[n-1-i].x=a[i].x;//映射
    b[0].x=0.0;
    for(int i=1;i<n;i++)
        b[i].x=1.0/i/i;
    init();
    FFT(a,1),FFT(b,1),FFT(aa,1);
    for(int i=0;i<lim;i++)
        c[i]=a[i]*b[i],cc[i]=aa[i]*b[i];
    FFT(c,-1),FFT(cc,-1);
    for(int i=0;i<n;i++)
    printf("%.3lf\n",c[i].x-cc[n-1-i].x);//后面取n-1-i项
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值