考虑$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 }