题目传送门

题目大意:给你一个长度为$n$的自然数序列$a$,定义一段区间的权值为这一段区间里所有数的和,分别输出权值为$[0,\sum a_{i}]$的区间的长度之和

想到了生成函数的话,这道题并不难做。但很多细节真是不太好搞

我们首先预处理出前缀和s,那么一段区间$[l,r]$的权值就是$s_{r}-s_{l-1}$

容易联想到卷积

第一个多项式是 区间右端点的前缀和 作为指数的生成函数,每一项的系数是 右端点的编号之和

第二个多项式是 区间左端点的前缀和 作为指数的生成函数,每一项的系数是 左端点的编号之和

然而区间长度是相减而不是相乘

我们可以把问题转化成 右端点编号$*1$-左端点编号$*1$,求两次卷积再相减即可

然而左端点的前缀和是负数,我们把生成函数整体右移

然而序列里还有$0$的情况

如果序列里出现了连续的$0$,我们发现这部分答案我们无法通过卷积统计

因为按照我们的方法,在多项式对应的相同的位置卷积的话,两次统计的答案就被减掉了

所以连续的$0$对答案的影响通过$O(n)$扫一遍统计

每新加入一个新的$0$,就会多产生一个等差数列的贡献

另外答案比较大,$FFT$需要开$long\;double$

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 (1<<18)
#define M1 (N1<<1)
#define il inline
#define dd double
#define ld long double
#define ll long long
using namespace std; int T,n; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} const ld pi=acos(-);
struct cp{
ld x,y;
friend cp operator + (const cp &s1,const cp &s2){ return (cp){s1.x+s2.x,s1.y+s2.y}; }
friend cp operator - (const cp &s1,const cp &s2){ return (cp){s1.x-s2.x,s1.y-s2.y}; }
friend cp operator * (const cp &s1,const cp &s2){ return (cp){s1.x*s2.x-s1.y*s2.y,s1.y*s2.x+s1.x*s2.y}; }
}a[N1],b[N1],c[N1];
int r[N1];
void FFT(cp *s,int len,int type)
{
int i,j,k; cp wn,w,t;
for(i=;i<len;i++) if(i<r[i]) swap(s[i],s[r[i]]);
for(k=;k<=len;k<<=)
{
wn=(cp){cos(pi*2.0*type/k),sin(pi*2.0*type/k)};
for(i=;i<len;i+=k)
{
w=(cp){,};
for(j=;j<(k>>);j++,w=w*wn)
{
t=w*s[i+j+(k>>)];
s[i+j+(k>>)]=s[i+j]-t;
s[i+j]=s[i+j]+t;
}
}
}
}
void FFT_Main(int len)
{
FFT(a,len,); FFT(b,len,);
for(int i=;i<len;i++) c[i]=a[i]*b[i];
FFT(c,len,-);
for(int i=;i<len;i++) c[i].x/=len;
} int v[N1],s[N1];
ll ans[N1]; int main()
{
scanf("%d",&T);
while(T--) { memset(v,,sizeof(v)); memset(s,,sizeof(s)); memset(r,,sizeof(r)); memset(ans,,sizeof(ans));
int i,j,maxn=,len,L,num;
scanf("%d",&n);
for(i=;i<=n;i++) v[i]=gint(), s[i]=s[i-]+v[i], maxn=max(maxn,s[i]);
if(!maxn)
{
for(i=;i<=n;i++)
ans[]+=1ll*(i+)*i/;
printf("%lld\n",ans[]);
continue;
} for(len=,L=;len<maxn+maxn+;len<<=,L++);
for(i=;i<len;i++) r[i]=(r[i>>]>>)|((i&)<<(L-)); memset(a,,sizeof(a)); memset(b,,sizeof(b));
for(i=;i<=n;i++) a[s[i]].x+=i;
for(i=;i<=n;i++) b[-s[i]+maxn].x++;
FFT_Main(len);
for(i=maxn;i<=(maxn<<);i++) ans[i-maxn]=(ll)(c[i].x+0.5); memset(a,,sizeof(a)); memset(b,,sizeof(b));
for(i=;i<=n;i++) a[s[i]].x++;
for(i=;i<=n;i++) b[-s[i]+maxn].x+=i;
FFT_Main(len);
for(i=maxn;i<=(maxn<<);i++) ans[i-maxn]-=(ll)(c[i].x+0.5); for(i=,num=;i<=n;i++)
if(!v[i]){ num++; ans[]+=1ll*(num+)*(num)/2ll; }
else{ num=; }
for(i=;i<=maxn;i++) printf("%lld\n",ans[i]);
//puts("");
}
return ; }

HDU 5307 He is Flying (生成函数+FFT)的更多相关文章

  1. FFT(快速傅里叶变换):HDU 5307 He is Flying

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA8IAAAPeCAIAAABInTQaAAAgAElEQVR4nOy9fZReVXk3vP8ia+HqCy

  2. HDU 5307 He is Flying ——FFT

    卷积的妙用,显然我们可以求出所有符合条件的右端点的和,然后减去左端点的和. 就是最后的答案.然后做一次前缀和,然后就变成了统计差是一个定值的情况. 令$A(s[i])++$ $B(s[i])+=i$ ...

  3. hdu 1402 A * B Problem Plus FFT

    /* hdu 1402 A * B Problem Plus FFT 这是我的第二道FFT的题 第一题是完全照着别人的代码敲出来的,也不明白是什么意思 这个代码是在前一题的基础上改的 做完这个题,我才 ...

  4. loj6570 毛毛虫计数(生成函数FFT)

    link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...

  5. HDU - 5307 :He is Flying (分治+FFT)(非正解)

    JRY wants to drag racing along a long road. There are nn sections on the road, the ii-th section has ...

  6. HDU 5515 Game of Flying Circus 二分

    Game of Flying Circus Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem ...

  7. 挑选队友 (生成函数 + FFT + 分治)

    链接:https://www.nowcoder.com/acm/contest/133/D来源:牛客网 题目描述 Applese打开了m个QQ群,向群友们发出了组队的邀请.作为网红选手,Applese ...

  8. 【BZOJ3771】Triple 生成函数 FFT 容斥原理

    题目大意 有\(n\)把斧头,不同斧头的价值都不同且都是\([0,m]\)的整数.你可以选\(1\)~\(3\)把斧头,总价值为这三把斧头的价值之和.请你对于每种可能的总价值,求出有多少种选择方案. ...

  9. HDU - 1402 A * B Problem Plus FFT裸题

    http://acm.hdu.edu.cn/showproblem.php?pid=1402 题意: 求$a*b$ 但是$a$和$b$的范围可以达到 $1e50000$ 题解: 显然...用字符串模拟 ...

随机推荐

  1. MEAN框架学习笔记

    MEAN框架学习笔记 MEAN开发框架的资料非常少.基本的资料还是来自于learn.mean.io站点上的介绍. 于是抱着一种零基础学习的心态,在了解的过程中,通过翻译加上理解将MEAN框架一点点消化 ...

  2. POJ 2914

    无向图全局最小割算法 求 G=(V, E)中任意 s-t 最小割的算法: 定义w(A, x) = ∑w(v[i], x),v[i]  A ∈  定义 Ax 为在x 前加入 A 的所有点的集合(不包括 ...

  3. libyuv库的使用

    libyuv是Google开源的实现各种YUV与RGB之间相互转换.旋转.缩放的库.它是跨平台的,可在Windows.Linux.Mac.Android等操作系统.x86.x64.arm架构上进行编译 ...

  4. Linux GDB程序调试工具使用简单介绍

    GDB概述 GDB是GNU开源组织公布的一个强大的UNIX下的程序调试工具.也许,各位比較喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但假设你是在UNIX平台下做软件,你会发现GDB这个调试 ...

  5. fputs与fgets

    1.      fputs 函数名: fputs  功  能: 送一个字符到一个流中  用  法: int fputs(char *string, FILE *stream); 说明: fputs是一 ...

  6. spring 源码解析

    1. [文件] spring源码.txt ~ 15B     下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB     下载( ...

  7. MFC 程序的运行流程

    CWinApp::InitApplication CMyWinApp::InitInstance CMyFrameWnd::CMyFrameWnd CFrameWnd::Create CWnd::Cr ...

  8. netpbm开机logo制作工作【转】

    本文转载自: http://www.fx114.net/qa-19-74437.aspx

  9. WebRequestSugar

    用法 WebRequestSugar ws = new WebRequestSugar(); //可选参数 //ws.SetAccept //ws.SetContentType //ws.SetCoo ...

  10. javascript设计模式-继承

    javascript继承分为两种:类式继承(原型链.extend函数).原型式继承(对继承而来的成员的读和写的不对等性.clone函数). 类式继承-->prototype继承: functio ...