zoukankan      html  css  js  c++  java
  • hdu5307 He is Flying

    题目描述

    题解:

    首先一看区间和就知道是预处理前缀和。

    区间$[l,r]$求和是$s[r]-s[l-1]$。(废话

    然后感觉这道题好毒瘤啊。。。

    好像是构造。

    后来才知道官方题解真的给了个多项式。

    具体实现就是,有两个多项式$A,B$,

    第一次,对于这个前缀和$s$,我们让$A[s]+=s_{len},B[S-s]++$,

    其中$S$指总和。

    然后求$A*B$,得到的多项式第$i+S$项系数就是所有区间和为$i$的区间的$r$之和。

    第二次,我们让$A[s]++,B[S-s]+=s_{len}$,

    $A*B$的第$i+S$系数就是$l-1$之和。

    最后减一下就好了。

    但是算$0$时会有麻烦。比如区间我减我自己得到个$0$,

    读进来的时候维护一下连续的$0$对答案的影响即可。

    $FFT$精度不够要开$long double$。

    出题人真$nb$。

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const long double Pi = acos(-1.0);
    const int N = 400050;
    template<typename T>
    inline void read(T&x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        x = f*c;
    }
    struct cp
    {
        long double x,y;
        cp(){}
        cp(long double x,long double y):x(x),y(y){}
        cp operator + (const cp&a)const{return cp(x+a.x,y+a.y);}
        cp operator - (const cp&a)const{return cp(x-a.x,y-a.y);}
        cp operator * (const cp&a)const{return cp(x*a.x-y*a.y,x*a.y+y*a.x);}
    };
    int to[N];
    void fft(cp *a,int len,int k)
    {
        for(int i=0;i<len;i++)
            if(i<to[i])swap(a[i],a[to[i]]);
        for(int i=1;i<len;i<<=1)
        {
            cp w0(cos(Pi/i),k*sin(Pi/i));
            for(int j=0;j<len;j+=(i<<1))
            {
                cp w(1,0);
                for(int o=0;o<i;o++,w=w*w0)
                {
                    cp w1 = a[j+o],w2 = a[j+o+i]*w;
                    a[j+o] = w1+w2;
                    a[j+o+i] = w1-w2;
                }
            }
        }
        if(k==-1)
            for(int i=0;i<len;i++)
                a[i].x/=len;
    }
    int T,n,a[N],s[N],lim=1,l;
    ll ans[N];
    cp A[N],B[N],C[N];
    int main()
    {
        read(T);
        while(T--)
        {
            read(n);
            memset(A,0,sizeof(A));
            memset(B,0,sizeof(B));
            memset(ans,0,sizeof(ans));
            ll ans0 = 0,cnt = 0;
            for(int i=1;i<=n;i++)
            {
                read(a[i]);
                s[i] = s[i-1]+a[i];
                if(!a[i])
                {
                    cnt++;
                    ans0+=cnt*(cnt+1)/2;
                }else cnt=0;
            }
            printf("%I64d
    ",ans0);
            lim = 1,l = 0;
            while(lim<=2*s[n])lim<<=1,l++;
            for(int i=1;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(l-1)));
            for(int i=1;i<=n;i++)
            {
                A[s[i]].x+=i;
                B[s[n]-s[i-1]].x++;
            }
            fft(A,lim,1),fft(B,lim,1);
            for(int i=0;i<lim;i++)C[i]=A[i]*B[i];
            fft(C,lim,-1);
            for(int i=1;i<=s[n];i++)
                ans[i]+=(ll)(C[i+s[n]].x+0.1);
            for(int i=0;i<lim;i++)A[i]=B[i]=cp(0,0);
            for(int i=1;i<=n;i++)
            {
                A[s[i]].x++;
                B[s[n]-s[i-1]].x+=i-1;
            }
            fft(A,lim,1),fft(B,lim,1);
            for(int i=0;i<lim;i++)C[i]=A[i]*B[i];
            fft(C,lim,-1);
            for(int i=1;i<=s[n];i++)
                printf("%I64d
    ",ans[i]-(ll)(C[i+s[n]].x+0.1));
        }
        return 0;
    }
  • 相关阅读:
    下载最新Silverlight 5 Beta客户端
    oracle数据库导入导出命令!
    使用SQL Server 2008提供的表分区向导
    Microsoft Visual Studio 2010 旗舰版下载地址
    用C#创建Windows服务(Windows Services)
    Socket通信:服务端发送安全策略到flash(c#)
    Microsoft Silverlight 4 Tools for Visual Studio 2010 下载地址
    Flex打印
    .NET中三种数据类型转换的区别:(type), type.Parse, Convert类
    JQUERY 常用方法大全
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10284127.html
Copyright © 2011-2022 走看看