zoukankan      html  css  js  c++  java
  • P3338 [ZJOI2014]力

    思路

    颓柿子的题目

    要求求这样的一个式子

    [F_j=sum_{i<j}frac{q_iq_j}{(i-j)^2}-sum_{i>j}frac{q_iq_j}{(i-j)^2} ]

    (E_i=frac{F_i}{q_i}),求所有的(E_i)

    对于Ei,显然可以

    [E_i=sum_{j=0}^{i-1}frac{q_j}{(i-j)^2}-sum_{j=i+1}^nfrac{q_j}{(i-j)^2} ]

    前后没什么关联,可以分开考虑,首先考虑前面部分

    [sum_{j=0}^{i-1}frac{q_j}{(i-j)^2} ]

    (f(i)=q_i)(g(i)=frac{1}{i^2})

    则前面一部分变为

    [sum_{j=0}^{i-1}f(j)g(i-j) ]

    变成了卷积的形式

    后面一部分是

    [sum_{j=i+1}^{n}frac{q_j}{(i-j)^2} ]

    同理变成

    [sum_{j=i+1}^nf(j)g(j-i) ]

    似乎没什么办法,但是我们可以把(f)整个反过来(就是(f(1))(f(n))交换,与(f(2))(f(n-1))交换)

    设交换之后的(f)(f')(f'_i=f_{n-i+1})

    则有

    [sum_{j=0}^{i-1}f'(j)g(j-i) ]

    则原来的第i项和反转后的第(n-i+1)项相同

    对应相减即可

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define int long long
    using namespace std;
    const double pi = acos(-1.0);
    struct complex{//a+bi
        double a,b;
        complex operator + (complex &bx){
            return (complex){a+bx.a,b+bx.b};
        }
        complex operator - (complex &bx){
            return (complex){a-bx.a,b-bx.b};
        }
        complex operator * (complex &bx){
            return (complex){a*bx.a-b*bx.b,b*bx.a+a*bx.b};
        }
        complex conj(void){
            return (complex){a,-b};
        }
    };
    int n;
    double q[401000],ans[401000];
    complex inv[401000],wnk[401000],a[401000],b[401000];
    void init(int len){
        for(int i=0;i<len;i++){
            wnk[i]=(complex){cos(2*pi*i/len),sin(2*pi*i/len)};
            inv[i]=wnk[i].conj();
        }
    }
    void FFT(complex *a,complex *opt,int n){
        int lim=0;
        while((1<<lim)<n){
            lim++;
        }
        n=(1<<lim);
        for(int i=0;i<n;i++){
            int t=0;
            for(int j=0;j<lim;j++)
                if((i>>j)&1)
                    t|=(1<<(lim-j-1));
            if(t<i)
                swap(a[i],a[t]);
        }
        for(int i=2;i<=n;i<<=1){
            int len=i/2;
            for(complex *j=a;j!=a+n;j+=i){
                for(int k=0;k<len;k++){
                    complex t=j[k+len]*opt[n/i*k];
                    j[k+len]=j[k]-t;
                    j[k]=j[k]+t;
                }
            }
        }
    }
    void Do_FFT(int n){
        int lim=0;
        while((1<<lim)<n){
            lim++;
        }
        n=(1<<lim);
        init(n);
        FFT(a,wnk,n);
        FFT(b,wnk,n);
        for(int i=0;i<n;i++)
            a[i]=a[i]*b[i];
        FFT(a,inv,n);
        for(int i=0;i<n;i++)
            a[i].a/=n;
    }
    signed main(){
        // freopen("1.in","r",stdin);
        // freopen("test.out","w",stdout);
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lf",&q[i]);
        }
        for(int i=1;i<=n;i++){
            a[i].a=q[i];
            b[i].a=1.0/(i*i);
            a[i].b=0;
            b[i].b=0;
        }
        Do_FFT(2*n+4);
        for(int i=1;i<=n;i++)
            ans[i]=a[i].a;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++){
            a[i].a=q[i];
            b[i].a=1.0/(i*i);
            a[i].b=0;
            b[i].b=0;
        }
        for(int i=1,j=n;i<j;i++,j--)
            swap(a[i],a[j]);
        Do_FFT(2*n+4);
        for(int i=1;i<=n;i++)
            ans[i]-=a[n-i+1].a;
        for(int i=1;i<=n;i++)
            printf("%.3lf
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    JS中的this
    VS下遇到未能加载文件或程序集 错误
    观察者模式实现INotifyPropertyChanged
    看书不仔细的下场
    Android 解析XML
    杂想
    Android 对话框用法
    Android之AlertDialog.Builder详解
    Android:开机自启动并接收推送消息
    Clojure:通过ZeroMQ推送消息
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10559235.html
Copyright © 2011-2022 走看看