• BZOJ4133 : Answer的排队


    设$f[i][j]$表示考虑前$i$个人,第$i$个人在前$i$个人中排名为$j$的方案数。

    对于大小关系相同的一段,转移可以看成求$k$次前/后缀和,任意一项对另一项的贡献仅和其下标差值有关,FFT加速即可。

    时间复杂度$O(mnlog n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=65555,M=32768,P=1000000007;
    int n,m,i,j,k,t,o,len,L,R,a[30],b[N],f[N*3],ans,g[N],v[N],fin[N],fac[N],inv[N],pos[N];
    inline void up(int&a,int b){(a+=b)>=P&&(a-=P);}
    inline int C(int n,int m){return 1LL*fac[n]*inv[m]%P*inv[n-m]%P;}
    namespace FFT{
    struct comp{
      long double r,i;comp(long double _r=0,long double _i=0){r=_r;i=_i;}
      comp operator+(const comp&x){return comp(r+x.r,i+x.i);}
      comp operator-(const comp&x){return comp(r-x.r,i-x.i);}
      comp operator*(const comp&x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
      comp conj(){return comp(r,-i);}
    }A[N],B[N];
    int a0[N],b0[N],a1[N],b1[N];
    const long double pi=acos(-1.0);
    void FFT(comp a[],int n,int t){
      for(int i=1;i<n;i++)if(i<pos[i])swap(a[i],a[pos[i]]);
      for(int d=0;(1<<d)<n;d++){
        int m=1<<d,m2=m<<1;
        long double o=pi*2/m2*t;comp _w(cos(o),sin(o));
        for(int i=0;i<n;i+=m2){
          comp w(1,0);
          for(int j=0;j<m;j++){
            comp&A=a[i+j+m],&B=a[i+j],t=w*A;
            A=B-t;B=B+t;w=w*_w;
          }
        }
      }
      if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
    }
    void mul(int*a,int*b,int*c,int k){
      int i,j;
      for(i=0;i<k;i++)A[i]=comp(a[i],b[i]);
      FFT(A,k,1);
      for(i=0;i<k;i++){
        j=(k-i)&(k-1);
        B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*comp(0,-0.25);
      }
      FFT(B,k,-1);
      for(i=0;i<k;i++)c[i]=((long long)(B[i].r+0.5))%P;
    }
    void mulmod(int*a,int*b,int*c,int k){
      int i;
      for(i=0;i<k;i++)a0[i]=a[i]/M,b0[i]=b[i]/M;
      for(mul(a0,b0,a0,k),i=0;i<k;i++){
        c[i]=1LL*a0[i]*M*M%P;
        a1[i]=a[i]%M,b1[i]=b[i]%M;
      }
      for(mul(a1,b1,a1,k),i=0;i<k;i++){
        c[i]=(a1[i]+c[i])%P,a0[i]=(a0[i]+a1[i])%P;
        a1[i]=a[i]/M+a[i]%M,b1[i]=b[i]/M+b[i]%M;
      }
      for(mul(a1,b1,a1,k),i=0;i<k;i++)c[i]=(1LL*M*(a1[i]-a0[i]+P)+c[i])%P;
    }
    }
    inline void solve(int len,int K){
      int i,j,k;
      for(k=1;k<=len;k<<=1);k<<=1;
      j=__builtin_ctz(k)-1;
      for(i=0;i<k;i++)pos[i]=pos[i>>1]>>1|((i&1)<<j);
      for(i=0;i<=len;i++)v[i]=C(i+K-1,K-1);
      for(g[0]=0;i<k;i++)v[i]=g[i]=0;
      FFT::mulmod(g,v,fin,k);
      for(i=1;i<=len;i++)g[i]=fin[i];
    }
    int main(){
      scanf("%d%d",&n,&m);
      for(fac[0]=i=1;i<=n*2;i++)fac[i]=1LL*fac[i-1]*i%P;
      for(inv[0]=inv[1]=1,i=2;i<=n*2;i++)inv[i]=1LL*(P-P/i)*inv[P%i]%P;
      for(i=2;i<=n*2;i++)inv[i]=1LL*inv[i-1]*inv[i]%P;
      for(i=1;i<=m;i++)scanf("%d",&a[i]);
      for(i=1;i<m;i++)for(j=a[i];j<a[i+1];j++)b[j]=i&1;
      for(i=a[2],L=1+N,f[R=i+N]=1;i<n;i=j){
        for(j=i;j<n&&b[i]==b[j];j++);
        t=j-i;
        for(k=L;k<=R;k++)g[k-L+1]=f[k];
        len=R-L+1;
        if(!b[i])reverse(g+1,g+len+1);
        solve(len,t);
        if(!b[i])reverse(g+1,g+len+1);
        for(k=L;k<=R;k++)f[k]=g[k-L+1];
        b[i]?L-=t:R+=t;
      }
      for(i=L;i<=R;i++)up(ans,f[i]);
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    SQL优化
    Mybatis
    Spring MVC(总结二)
    ES多机集群配置
    ES索引,分片,一致性
    ElasticSearch关于索引库的命令操作
    试题01(一)
    Linux安装配置elastic search
    Windows安装配置elastic search
    SpringBoot(二)
  • 原文地址:https://www.cnblogs.com/clrs97/p/8442920.html
Copyright © 2020-2023  润新知