JRY wants to drag racing along a long road. There are 0.

InputThe first line of the input is a single integer i−1. 
Sample Input

2
3
1 2 3
4
0 1 2 3

Sample Output

0
1
1
3
0
2
3
1
3
1
6
0
2
7

题意:总区间中有n个数(n<=100000),求每种区间和,累加出所对应的区间长度(j-i+1)和;

思路:可以通过母函数得到方程,然后FFT求。 也有一种暴力一点的方式,分治+FFT:即求跨过每个点的区间的贡献。 然后两次FFT分别算出左边和右边的贡献。

(4900ms卡过去了。要用long double。

母函数的方法可以看:https://blog.csdn.net/kyleyoung_ymj/article/details/51712329

#include<bits/stdc++.h>
#define ll long long
#define double long double
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep2(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int maxn=500010;
const double pi=acos(-1.0);
struct cp
{
    double r,i;
    cp(){}
    cp(double rr,double ii):r(rr),i(ii){}
    cp operator +(const cp&x)const{return cp(r+x.r,i+x.i);}
    cp operator -(const cp&x)const{return cp(r-x.r,i-x.i);}
    cp operator *(const cp&x)const{return cp(r*x.r-i*x.i,i*x.r+r*x.i);}
};
ll ans[maxn];int s[maxn],sum[maxn],R[maxn],n;
cp a[maxn],b[maxn],W,w,p;
void read(int &x){
    x=0; char c=getchar();
    while(c>'9'||c<'0') c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
}
inline void fft(cp*c,int t)
{
    int i,j,k;
    for(i=0;i<n;i++) R[i]<i?swap(c[R[i]],c[i]),0:0;
    for(i=1;i<n;i<<=1)
     for(j=0,W={cos(pi/i),sin(pi/i)*t};j<n;j+=i<<1)
      for(k=0,w={1,0};k<i;k++,w=w*W)
       p=c[j+k+i]*w,c[j+k+i]=c[j+k]-p,c[j+k]=c[j+k]+p;
}
void solve(int l,int r)
{
    if(l==r){ ans[s[l]]++; return ;}
    int mid=(l+r)>>1 ,delta=sum[r]-sum[l-1];
    solve(l,mid); solve(mid+1,r);
    for(n=1;(n-1)<=delta;n<<=1);
    rep(i,1,n-1) R[i]=R[i>>1]>>1|(i&1?n>>1:0);

    rep2(i,mid,l) a[sum[mid]-sum[i-1]].r+=mid-i+1;
    rep(i,mid+1,r) ++b[sum[i]-sum[mid]].r;
    fft(a,1); fft(b,1);
    rep(i,0,n-1) a[i]=a[i]*b[i];
    fft(a,-1);
    rep(i,0,delta) ans[i]+=(ll)((a[i].r)/n+0.5);
    rep(i,0,n) a[i]=b[i]=cp(0.,0.);

    rep2(i,mid,l) ++a[sum[mid]-sum[i-1]].r;
    rep(i,mid+1,r) b[sum[i]-sum[mid]].r+=i-mid;
    fft(a,1); fft(b,1);
    rep(i,0,n-1) a[i]=a[i]*b[i];
    fft(a,-1);
    rep(i,0,delta) ans[i]+=(ll)((a[i].r)/n+0.5);
    rep(i,0,n) a[i]=b[i]=cp(0.,0.);
}
int main()
{
    int N,T;
    scanf("%d",&T);
    while(T--){
        read(N);
        rep(i,1,N) read(s[i]),sum[i]=sum[i-1]+s[i];
        rep(i,0,sum[N]) ans[i]=0;
        solve(1,N);
        rep(i,0,sum[N]) printf("%lld\n",ans[i]);
    }
    return 0;
}

 

相关文章:

  • 2022-12-23
  • 2022-01-02
  • 2022-12-23
  • 2022-01-02
  • 2022-02-28
猜你喜欢
  • 2021-10-11
  • 2022-01-19
  • 2021-04-12
  • 2021-08-17
  • 2021-06-04
  • 2021-12-22
  • 2021-10-12
相关资源
相似解决方案