[ZJOI2014]力

Description:

给出n个数qi,

给出Fj的定义如下:\(F_j = \sum_{i<j}\frac{q_i q_j}{(i-j)^2 }-\sum_{i>j}\frac{q_i q_j}{(i-j)^2 }\)

令Ei=Fi/qi,求Ei.

Hint:

\(n \le 10^5\)

Solution:

\(F_j=\sum_{i=1}^{j-1} f(i)*g(j-i)-\sum_{i=j+1}^nf(i)*g(j-i)\)

\(F_j=\sum_{i=1}^{j-1} f(i)*g(j-i)-\sum_{i=1}^{n-j}f(n-i+1)*g(j-(n-i+1))\)

将\(f\)翻转

\(F_j=\sum_{i=1}^{j-1} f(i)*g(j-i)-\sum_{i=1}^{n-j}f(i)^{'}*g((n-j)-i+1)\)

直接FFT求卷积即可

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=1e5+5;
const long double PI=acos(-1.0);
int n,l,lim=1,r[mxn];
inline int read() {
    char c=getchar(); int x=0,f=1;
    while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
    return x*f;
}
inline int chkmax(int &x,int y) {if(x<y) x=y;}
inline int chkmin(int &x,int y) {if(x>y) x=y;}

struct ed {
    int to,nxt;
}t[mxn<<1];

struct cp {
    long double x,y;
    cp (long double xx=0,long double yy=0) {x=xx;y=yy;}
    friend cp operator + (cp a,cp b) {
        return cp(a.x+b.x,a.y+b.y);
    }
    friend cp operator - (cp a,cp b) {
        return cp(a.x-b.x,a.y-b.y);
    }
    friend cp operator * (cp a,cp b) {
        return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
    }
}a[mxn],b[mxn],c[mxn];

void FFT(cp *p,int opt)
{
    for(int i=0;i<lim;++i)
        if(i<r[i]) swap(p[i],p[r[i]]);
    for(int mid=1;mid<lim;mid<<=1) {
        cp wn=cp(cos(PI/mid),opt*sin(PI/mid));
        for(int len=mid<<1,j=0;j<lim;j+=len) {
            cp w=cp(1,0);
            for(int k=0;k<mid;++k,w=w*wn) {
                cp x=p[j+k],y=w*p[j+mid+k];
                p[j+k]=x+y; p[j+mid+k]=x-y;
            }
        }
    }
}

int main()
{
    n=read();
    for(int i=1;i<=n;++i) {
        scanf("%Lf",&a[i].x);
        b[n-i+1].x=a[i].x;
        c[i]=1.0/i/i;
    }
    while(lim<=n*2) lim<<=1,++l;
    for(int i=0;i<lim;++i)
        r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));   
    FFT(a,1); FFT(b,1); FFT(c,1);
    for(int i=0;i<=lim;++i) a[i]=a[i]*c[i];
    for(int i=0;i<=lim;++i) b[i]=b[i]*c[i];
    FFT(a,-1); FFT(b,-1);
    for(int i=1;i<=n;++i) 
        printf("%.6Lf\n",a[i].x/lim+0.5-(b[n-i+1].x/lim+0.5));
    return 0;
}

上一篇:力 HYSBZ - 3527


下一篇:【opencv】轮廓分层()