题意:n个点 每个点价值为v[i],区间[l,r]的长度为r-l+1 区间价值为该区间内所有v[i]之和.
n<=1e5,v[i]累加和s<=5e4. 问区间价值为x时,这些区间长度的累加和. x=0,1,2...s.
答案:res[s[i]-s[j-1]]+=i-j+1 s[i]为前缀和i .O(n^2) TLE...
参考 S肯定也要指数,系数要体现和为S的区间的长度,则用两个前缀相减来表示
构造多项式:(∑ixsi)(∑x−si−1)−(∑xsi)(∑(i−1)x−si−1).
最后X^S的系数也就是要求的答案
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=1e5+5,M=(1<<17)+5;
const ld pi=acos(-1.0);
int sum[N],rev[M];
struct C{
ld real,imag;
C(ld real=0,ld imag=0):real(real),imag(imag){}
friend C operator +(C A,C B){
return C(A.real+B.real,A.imag+B.imag);
}
friend C operator -(C A,C B){
return C(A.real-B.real,A.imag-B.imag);
}
friend C operator *(C A,C B){
return C(A.real*B.real-A.imag*B.imag,A.imag*B.real+A.real*B.imag);
}
}A[M],B[M],ans[2][M];
void rd(int &res){
res=0;
char c;
while(c=getchar(),c<48);
do res=(res<<3)+(res<<1)+(c^48);
while(c=getchar(),c>47);
}
void FFT(C *arr,int n,int flag){
for(int i=0;i<n;++i)
if(i<rev[i])
swap(arr[i],arr[rev[i]]);
for(int m=2;m<=n;m<<=1){
C wm(cos(2*pi/m),flag*sin(2*pi/m));
for(int i=0;i<n;i+=m){
C w(1,0);
for(int j=0;j<m>>1;++j,w=w*wm){
C x=arr[i+j],y=w*arr[i+j+(m>>1)];
arr[i+j]=x+y;
arr[i+j+(m>>1)]=x-y;
}
}
}
}
void calc_FFT(int n,bool id){
int _n=n,m=n<<1,S=0;
for(n=1;n<=m;n<<=1,++S);
rev[0]=0;
for(int i=1;i<n;++i)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(S-1));
for(int i=_n+1;i<n;++i)
A[i]=B[i]=0;
FFT(A,n,1);
FFT(B,n,1);
for(int i=0;i<n;++i)
ans[id][i]=A[i]*B[i];
FFT(ans[id],n,-1);
for(int i=0;i<=m;++i)
ans[id][i].real/=n;
}
void solve()
{
ll ans0=0;
int n;
scanf("%d",&n);
sum[0]=0;
for(int i=1,v,cnt=0;i<=n;i++)
{
scanf("%d",&v),sum[i]=sum[i-1]+v;
if(v==0)
{
++cnt;
ans0+=1ll*cnt*(cnt+1)/2;
}
else
cnt=0;
}
printf("%I64d\n",ans0);
for(int i=0;i<=sum[n];i++)
A[i]=B[i]=0;
for(int i=1;i<=n;i++)
{
A[sum[i]].real+=i;
B[-sum[i-1]+sum[n]].real+=1;//¸ºÏµÊýÀëÉ¢»¯
}
calc_FFT(sum[n],0);
for(int i=0;i<=sum[n];++i)
A[i]=B[i]=0;
for(int i=1;i<=n;++i)
{
A[sum[i]].real+=1;
B[-sum[i-1]+sum[n]].real+=i-1;
}
calc_FFT(sum[n],1);//1 id
for(int i=1;i<=sum[n];i++)
printf("%I64d\n",(ll)(ans[0][i+sum[n]].real-ans[1][i+sum[n]].real+0.5));
}
int main()
{
int T;
cin>>T;
while(T--)
solve();
return 0;
}
构造多项式:(∑ixsi)(∑x−si−1)−(∑xsi)(∑(i−1)x−si−1).