P3338 [ZJOI2014]力 [FFT]

P 3338 [ Z J O I 2014 ] 力 P3338 [ZJOI2014]力 P3338[ZJOI2014]

给出n个数qi,给出Fj的定义如下:

F j = ∑ i &lt; j q i q j ( i − j ) 2 − ∑ i &gt; j q i q j ( i − j ) 2 F_j = \sum_{i&lt;j}\frac{q_i q_j}{(i-j)^2 }-\sum_{i&gt;j}\frac{q_i q_j}{(i-j)^2 } Fj=i<j(ij)2qiqji>j(ij)2qiqj

E i = F i / q i Ei=Fi/qi Ei=Fi/qi,求 E i Ei Ei.


Solution

E i = F i / q i = ∑ j &lt; i q j ( j − i ) 2 − ∑ j &gt; i q j ( j − i ) 2 Ei = F_i/q_i = \sum_{j&lt;i}\frac{q_j}{(j-i)^2 }-\sum_{j&gt;i}\frac{q_j}{(j-i)^2 } Ei=Fi/qi=j<i(ji)2qjj>i(ji)2qj

x i = i 2 x_i = i^2 xi=i2
E i = ∑ j &lt; i q j x j − i − ∑ j &gt; i q j x j − i Ei = \sum_{j&lt;i}q_jx_{j-i} - \sum_{j&gt;i}q_jx_{j-i} Ei=j<iqjxjij>iqjxji

E i = ∑ j = 1 i − 1 q j x i − j − ∑ j = i + 1 n q j x i − j E_i = \sum_{j=1}^{i-1}q_jx_{i-j}-\sum_{j=i+1}^nq_jx_{i-j} Ei=j=1i1qjxijj=i+1nqjxij
这已经是卷积形式了
然而 减数 中的 x i − j x_{i-j} xij下标为负数, 所以转换成
E i = ∑ j = 1 i − 1 q j x i − j − ∑ j = i + 1 n q j x j − i E_i = \sum_{j=1}^{i-1}q_jx_{i-j}-\sum_{j=i+1}^nq_jx_{j-i} Ei=j=1i1qjxijj=i+1nqjxji
为了保持卷积形式, 继续设 b i = q n − i + 1 b_i = q_{n-i+1} bi=qni+1
E i = ∑ j = 1 i − 1 q j x i − j − ∑ j = i + 1 n b n − j + 1 x j − i E_i = \sum_{j=1}^{i-1}q_jx_{i-j}-\sum_{j=i+1}^nb_{n-j+1}x_{j-i} Ei=j=1i1qjxijj=i+1nbnj+1xji
这又是一个卷积形式了!!!
于是 F F T FFT FFT走起~


Attention

F F T FFT FFT要开2倍数组
不要漏掉蝴蝶变化


Code

#include<cstdio>
#include<cmath>
#include<algorithm>

const int maxn = 1e6 + 5;
const double Pi = acos(-1);

int N, N1, rev[maxn];

struct complex{ double x, y; complex(double x = 0, double y = 0):x(x), y(y) {} } q[maxn], A[maxn], C[maxn], B[maxn];

complex operator + (complex a, complex b){ return complex(a.x+b.x, a.y+b.y); }
complex operator - (complex a, complex b){ return complex(a.x-b.x, a.y-b.y); }
complex operator * (complex a, complex b){ return complex(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x); }

void FFT(complex *F, short Opt){
        for(int i = 0; i < N1; i ++)
                if(i < rev[i]) std::swap(F[i], F[rev[i]]);
        for(int p = 2; p <= N1; p <<= 1){
                int len = p >> 1;
                complex tmp(cos(Pi/len), Opt*sin(Pi/len));
                for(int i = 0; i < N1; i += p){
                        complex Buf(1, 0);
                        for(int k = i; k < i+len; k ++){
                                complex Temp = Buf * F[k+len];
                                F[k+len] = F[k] - Temp;
                                F[k] = F[k] + Temp;
                                Buf = Buf * tmp;
                        }
                }
        }
}

int main(){
        scanf("%d", &N);
        for(int i = 1; i <= N; i ++) scanf("%lf", &q[i].x), A[N-i+1] = q[i];
        for(int i = 1; i <= N; i ++) C[i].x = (1.0/(double)(i))/(double)(i);
        N1 = 1;
        int bit_num = 0;
        while(N1 <= (N<<1)) N1 <<= 1, bit_num ++;
        for(int i = 0; i < N1; i ++) rev[i] = (rev[i>>1]>>1)|((i&1) << bit_num-1);
        FFT(A, 1), FFT(q, 1), FFT(C, 1);
        for(int i = 0; i <= N1; i ++) B[i] = q[i] * C[i], A[i] = A[i] * C[i];
        FFT(A, -1), FFT(B, -1);
        for(int i = 1; i <= N; i ++) printf("%.3lf\n", (B[i].x - A[N-i+1].x)/N1);
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值