【BZOJ】3527: [Zjoi2014]力 FFT

【参考】「ZJOI2014」力 - FFT by menci

【算法】FFT处理卷积

【题解】将式子代入后,化为Ej=Aj-Bj。

Aj=Σqi*[1/(i-j)^2],i=1~j-1。

令f(i)=qi,g(i)=1/i^2,定义f(0)=g(0)=0(方便卷积)。

Aj=Σf(i)*g(j-i),i=0~j-1,标准的卷积形式。

而对于Bj,将g反转后就是和为i+n-1的标准卷积形式了。

第一次FFT后,记得对a数组后半部分清零后再进行第二次FFT。

复杂度O(n log n)。

#include<cstdio>
#include<algorithm>
#include<complex>
#include<cmath>
using namespace std;
const int maxn=300010;
const double PI=acos(-1);
complex<double>a1[maxn],a2[maxn];
int n;
double ans[maxn],b1[maxn],b2[maxn];
namespace fft{
    complex<double>o[maxn],oi[maxn];
    void init(int n){
        for(int k=0;k<n;k++)o[k]=complex<double>(cos(2*PI*k/n),sin(2*PI*k/n)),oi[k]=conj(o[k]);
    }
    void transform(complex<double>*a,int n,complex<double>*o){
        int k=0;
        while((1<<k)<n)k++;
        for(int i=0;i<n;i++){
            int t=0;
            for(int j=0;j<k;j++)if(i&(1<<j))t|=(1<<(k-j-1));
            if(i<t)swap(a[i],a[t]);
        }
        for(int l=2;l<=n;l*=2){
            int m=l/2;
            for(complex<double>*p=a;p!=a+n;p+=l){
                for(int i=0;i<m;i++){
                    complex<double>t=o[n/l*i]*p[i+m];
                    p[i+m]=p[i]-t;
                    p[i]+=t;
                }
            }
        }
    }
    void dft(complex<double>*a,int n){transform(a,n,o);}
    void idft(complex<double>*a,int n){transform(a,n,oi);for(int i=0;i<n;i++)a[i]/=n;}
}
void multply(int n){
    int N=1;
    while(N<n+n)N*=2;
    for(int i=0;i<N;i++)a1[i]=a2[i]=0;
    for(int i=0;i<n;i++)a1[i].real(b1[i]),a2[i].real(b2[i]);
    fft::init(N);fft::dft(a1,N);fft::dft(a2,N);
    for(int i=0;i<N;i++)a1[i]*=a2[i];
    fft::idft(a1,N);
}
int main(){
    scanf("%d",&n);n++;
    b1[0]=b2[0]=0;
    for(int i=1;i<n;i++){
        scanf("%lf",&b1[i]);
        b2[i]=1.0/i/i;
    }
    multply(n);
    for(int i=1;i<n;i++)ans[i]=a1[i].real();
    for(int i=0;i<n/2;i++)swap(b2[i],b2[n-i-1]);
    multply(n);
    for(int i=1;i<n;i++){
        ans[i]-=a1[i+n-1].real();
        printf("%.3lf\n",ans[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/onioncyc/p/8419255.html

时间: 2024-10-12 14:01:29

【BZOJ】3527: [Zjoi2014]力 FFT的相关文章

BZOJ 3527: [Zjoi2014]力 FFT

3527: [Zjoi2014]力 Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<1000000000 Output n行,第i行输出Ei.与标准答案误差不超过1e-2即可. Sample Input 5 4006373.885184 15375036.435759 1717456.469144 8514941.004912 1410681.34

BZOJ 3527: [Zjoi2014]力 [快速傅里叶变换]

3527: [Zjoi2014]力 Time Limit: 30 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1723  Solved: 1015[Submit][Status][Discuss] Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Input 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. n≤100000,0<qi<1000000000 Output n行,第i

[BZOJ 3527][Zjoi2014]力(FFT)

Description 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. Solution 设fi=qi gi=1/i/i(这里如果写成i*i可能会爆int) 那前半部分就是∑fi*gj-i 发现是一个卷积的形式 后半部分把数组反一下同理 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #define

数学(FFT):BZOJ 3527 [Zjoi2014]力

题目在这里:http://wenku.baidu.com/link?url=X4j8NM14MMYo8Q7uPE7-7GjO2_TXnMFA2azEbBh4pDf7HCENM3-hPEl4mzoe2wSoblrSOvMirfS7PsQ1OVjsdaCJhEaGNCpuUxFKoPvNvXa 裸的FFT,小心i*i爆int!!! 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #includ

bzoj 3527: [Zjoi2014]力【FFT】

大力推公式,目标是转成卷积形式:\( C_i=\sum_{j=1}^{i}a_jb_{i-j} \) 首先下标从0开始存,n-- \[ F_i=\frac{\sum_{j<i}\frac{q_jq_i}{(j-i)^2}-\sum_{j>i}\frac{q_jq_i}{(j-i)^2}}{q_i} \] \[ F_i=\sum_{j<i}\frac{q_j}{(j-i)^2}-\sum_{j>i}\frac{q_j}{(j-i)^2} \] 设 \[ a_i=\sum_{j<

bzoj 3527: [Zjoi2014]力

都说这是个FFT模板题 可我这种蒟蒻还是看了大半天... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #include<complex

3527: [Zjoi2014]力 - BZOJ

题目大意:给出n个数qi,定义 Fj为 令 Ei=Fi/qi,求Ei. 看了很久题解,终于有些眉目,因为知道要用FFT,所以思路就很直了 其实我们就是要±1/(j-i)^2 ( i-j大于0时为正,小于0时为负 ) 和 qi 的乘积要算到j这个位置上,这个满足卷积,所以用FFT优化,但是j-i有负数,所以我们就加上一个n 于是设pi={ i>n,1/(i-n)^2 i<n,-1/(n-i)^2 其他,0 } 然后就套FFT模板就行了 1 const 2 maxn=800100; 3 type

[Zjoi2014]力 FFT

#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; typedef double dd; const dd pi=acos(0.0)*2; #define N 400005 struct P{ dd x,y; P(dd A=0.0,dd B=0.0){ x=A; y=B; } P

[Zjoi2014]力(FFT/NTT)

[Zjoi2014]力(FFT,卷积) 题意:给定\(n\)个点电荷,排在单位数轴上,求每个点的场强 考虑每个\(i\)对于每个\(j\)的贡献,分析式子 \(E=\cfrac{q_i}{(j-i)^2}\) 令\(f(x)=\sum q_ix^i\) \(g(x)=\sum a_ix^i,a_i=i<0?-\frac{1}{i^2}:\frac{1}{i^2}\) \(g(x)\)每一项\(x\)的指数其实是\(j-i\)的值 求\(f(x)\cdot g(x)\)即可,注意负数系数的话偏移一