[loj3394]Tour

考虑$a_{i}\ge 0$的情况,维护可重集$S=\{a_{i}\}$,从前往后依次确定$a_{i}$

令$x,y$分别为$S$中的最小和最大值,取$a_{i}=\begin{cases}x&xy\le w\\y&xy>w\end{cases}$并在$S$中删除

记$Y=\{i\mid a_{i}=y\}$,则$a_{i}a_{j}>w$(其中$i<j$)当且仅当$i\in Y$

在此基础上,从前往后依次将$a_{i}$插入排列,限制即不与已加入的$Y$中元素相邻

显然两个$Y$中元素不会相邻,则$a_{i}$有$i-2\sum_{j\in Y}[j\le i]$种插入方式,并对所有$i$累乘即可

 

考虑$\exist a_{i}<0$的情况,记$A/B_{x}$分别表示$a_{i}\ge 0/<0$的元素段数恰为$x$​的方案数,则答案即
$$
\sum_{x=1}^{n}\left(2(x!)^{2}A_{x}B_{x}+(x-1)!x!A_{x}B_{x-1}+(x-1)!x!A_{x-1}B_{x}\right)
$$
根据对称性,不妨仅考虑$A_{x}$,即每个$a_{i}$的插入方式变为$(i-1)+x-2\sum_{j\in Y}[j\le i]$

记以此法求出的答案为$A'_{x}$,并对空段的情况容斥,即$A_{x}=\sum_{i=0}^{x}(-1)^{x-i}{x\choose i}A'_{i}$

注意到$A'_{x}$即是形如$\prod_{i=1}^{n}(x+z_{i})$的$n$个点值,分治FFT展开后多点求值即可

 

上述做法可能被卡常,下面给出一个常数较小的做法:

记$\Delta^{i}f(x)=\begin{cases}f(x)&i=0\\\Delta^{i-1}f(x+1)-\Delta^{i-1}f(x)&i\ge 1\end{cases}$,则$\Delta^{i}f(0)=\sum_{x=0}^{i}(-1)^{i-x}{i\choose x}f(x)$

当$f(x)$为下降幂多项式时,注意到$(x+1)^{\underline{n}}-x^{\underline{n}}=nx^{\underline{n-1}}$,则$\Delta^{i}f(0)=i!\cdot [x^{\underline{i}}]f(x)$

换言之,取$f(x)=\prod_{i=1}^{n}(x+z_{i})$,则$A_{x}=\Delta^{x}f(0)$,问题即求$f(x)$的下降幂的形式

使用分治FFT,并以下降幂多项式的形式存储结果,问题即将两个下降幂多项式相乘

考虑插$[0,n]$的点值,注意到$f(i)=i!\sum_{j=0}^{i}\frac{[x^{\underline{j}}]f(x)}{(i-j)!}$,逆过程即$[x^{\underline{i}}]f(x)=\sum_{j=0}^{i}\frac{(-1)^{i-j}j!f(j)}{(i-j)!}$

预处理$e^{x}$和$e^{-x}$的$DFT$结果,分治时从多项式取模$\rightarrow 6$次$DFT$

时间复杂度为$o(n\log^{2}n)$,可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 600005
  4 #define mod 998244353
  5 #define ll long long
  6 #define vi vector<int>
  7 #define mid (l+r>>1)
  8 int n,m,w,x,ans,fac[N],inv[N],rev[N],W[20][N][2];
  9 vi ex[20],Ex[20],a,b,v,A,B;
 10 int qpow(int n,int m){
 11     int s=n,ans=1;
 12     while (m){
 13         if (m&1)ans=(ll)ans*s%mod;
 14         s=(ll)s*s%mod,m>>=1;
 15     }
 16     return ans;
 17 }
 18 void init(int n){
 19     m=0;
 20     while ((1<<m)<n)m++;
 21     for(int i=0;i<(1<<m);i++)rev[i]=(rev[i>>1]>>1)+((i&1)<<m-1);
 22 }
 23 void ntt(vi &a,int p=0){
 24     for(int i=0;i<(1<<m);i++)
 25         if (i<rev[i])swap(a[i],a[rev[i]]);
 26     for(int i=2,t=0;i<=(1<<m);i<<=1,t++)
 27         for(int j=0;j<(1<<m);j+=i)
 28             for(int k=0;k<(i>>1);k++){
 29                 int x=a[j+k],y=(ll)W[t][k][p]*a[j+k+(i>>1)]%mod;
 30                 a[j+k]=x+y;if (a[j+k]>=mod)a[j+k]-=mod;
 31                 a[j+k+(i>>1)]=x-y;if (a[j+k+(i>>1)]<0)a[j+k+(i>>1)]+=mod; 
 32             }
 33     if (p){
 34         int s=qpow((1<<m),mod-2);
 35         for(int i=0;i<(1<<m);i++)a[i]=(ll)a[i]*s%mod;
 36     }
 37 }
 38 vi calc(int l,int r){
 39     if (l==r)return vi{v[l],1};
 40     vi v,vl=calc(l,mid),vr=calc(mid+1,r);
 41     init((r-l<<1)+3),v.resize(1<<m),vl.resize(1<<m),vr.resize(1<<m);
 42     ntt(vl),ntt(vr);
 43     for(int i=0;i<(1<<m);i++){
 44         vl[i]=(ll)vl[i]*ex[m][i]%mod;
 45         vr[i]=(ll)vr[i]*ex[m][i]%mod; 
 46     }
 47     ntt(vl,1),ntt(vr,1);
 48     for(int i=0;i<=r-l+1;i++)v[i]=(ll)vl[i]*vr[i]%mod*fac[i]%mod;
 49     ntt(v);
 50     for(int i=0;i<(1<<m);i++)v[i]=(ll)v[i]*Ex[m][i]%mod;
 51     ntt(v,1),v.resize(r-l+2);
 52     return v;
 53 }
 54 vi calc(vi a){
 55     int n=a.size(),l=0,r=n-1;
 56     if (!n)return vi{1};
 57     v.resize(n),sort(a.begin(),a.end());
 58     for(int i=0;i<n;i++){
 59         v[i]=(i-(n-r-1<<1)+mod)%mod;
 60         if ((ll)a[l]*a[r]<=w)l++;else r--;
 61     }
 62     v=calc(0,n-1);
 63     for(int i=0;i<=n;i++)v[i]=(ll)v[i]*fac[i]%mod;
 64     return v;
 65 }
 66 int main(){
 67     fac[0]=inv[0]=inv[1]=1;
 68     for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod;
 69     for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
 70     for(int i=1;i<N;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod;
 71     for(int i=0;i<20;i++){
 72         W[i][0][0]=W[i][0][1]=1;
 73         W[i][1][0]=qpow(3,(mod-1>>i+1));
 74         W[i][1][1]=qpow(W[i][1][0],mod-2);
 75         for(int j=2;j<(1<<i);j++){
 76             W[i][j][0]=(ll)W[i][j-1][0]*W[i][1][0]%mod;
 77             W[i][j][1]=(ll)W[i][j-1][1]*W[i][1][1]%mod;
 78         }
 79     }
 80     for(int i=1;i<20;i++){
 81         init(1<<i),ex[i].resize(1<<i),Ex[i].resize(1<<i);
 82         for(int j=0;j<(1<<i-1);j++){
 83             ex[i][j]=inv[j];
 84             Ex[i][j]=(j&1 ? (mod-inv[j])%mod : inv[j]);
 85         }
 86         ntt(ex[i]),ntt(Ex[i]);
 87     }
 88     scanf("%d%d",&n,&w);
 89     for(int i=1;i<=n;i++){
 90         scanf("%d",&x);
 91         if (x>=0)a.push_back(x);
 92         else b.push_back(-x);
 93     }
 94     A=calc(a),B=calc(b);
 95     A.resize(n+1),B.resize(n+1);
 96     for(int i=1;i<=n;i++)
 97         ans=(ans+2LL*A[i]*B[i]+(ll)A[i]*B[i-1]+(ll)A[i-1]*B[i])%mod;
 98     printf("%d\n",ans);
 99     return 0;
100 }
View Code

 

posted @ 2022-07-11 21:04  PYWBKTDA  阅读(64)  评论(0编辑  收藏  举报