HDU 5279 分治NTT 图的计数
思路:
显然每个子图内都是森林
去掉所有子图1和n都连通且每条大边都存在的情况
直接DP上
NTT优化一波
注意前两项的值..
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int mod=998244353,N=262144; int cases,n,R[N],fac[N],inv[N],A[N],B[N],h[N],f[N],g[N],jy; int power(int x,int y){ int r=1; while(y){ if(y&1)r=1ll*x*r%mod; x=1ll*x*x%mod,y>>=1; }return r; } void NTT(int *a,int f,int m){ int L=0,n; for(n=1;n<m;n<<=1)L++; for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1)); for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]); for(int l=1;l<n;l<<=1){ int wn=power(3,((mod-1)/(l<<1)*f+(mod-1))%(mod-1)); for(int j=0;j<n;j+=(l<<1)){ int w=1; for(int k=0;k<l;k++,w=1ll*w*wn%mod){ int x=a[j+k],y=1ll*w*a[j+k+l]%mod; a[j+k]=(x+y)%mod,a[j+k+l]=(x-y+mod)%mod; } } } if(f==-1){ int ni=power(n,mod-2); for(int i=0;i<n;i++)a[i]=1ll*a[i]*ni%mod; } } void cdq(int l,int r){ if(l==r){ if(l==1)f[l]=1; else f[l]=(1ll*f[l]*fac[l-1]+1ll*h[l]*fac[l-1])%mod; return; } int mid=(l+r)>>1; cdq(l,mid); int len1=mid-l+1,len2=r-l+1,len=1; while(len<len1+len2)len<<=1; for(int i=0;i<len1;i++)A[i]=1ll*f[l+i]*inv[l+i]%mod; for(int i=len1;i<len;i++)A[i]=0; for(int i=0;i<len2;i++)B[i]=h[i]; for(int i=len2;i<len;i++)B[i]=0; NTT(A,1,len),NTT(B,1,len); for(int i=0;i<len;i++)A[i]=1ll*A[i]*B[i]%mod; NTT(A,-1,len); for(int i=mid+1;i<=r;i++)f[i]=(f[i]+A[i-l])%mod; cdq(mid+1,r); } void init(){ fac[0]=h[1]=1; for(int i=1;i<=100000;i++)fac[i]=1ll*fac[i-1]*i%mod; inv[100000]=power(fac[100000],mod-2); for(int i=99999;~i;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod; for(int i=2;i<=100000;i++)h[i]=1ll*power(i,i-2)*inv[i-1]%mod; cdq(1,100000),f[0]=1; for(int i=0;i<262144;i++)A[i]=B[i]=0; for(int i=0;i<=100000;i++)A[i]=1ll*f[i]*inv[i]%mod; B[0]=B[1]=0; for(int i=2;i<=100000;i++)B[i]=1ll*h[i]*(i-1)%mod; NTT(A,1,262144),NTT(B,1,262144); for(int i=0;i<262144;i++)g[i]=1ll*A[i]*B[i]%mod; NTT(g,-1,262144),g[1]=1; for(int i=2;i<=100000;i++)g[i]=1ll*g[i]*fac[i-2]%mod; } int main(){ scanf("%d",&cases),init(); while(cases--){ scanf("%d",&n);int a1=1,a2=1; for(int i=1;i<=n;i++)scanf("%d",&jy),a1=1ll*a1*f[jy]%mod,a2=1ll*a2*g[jy]%mod; printf("%lld\n",(1ll*a1*power(2,n)%mod-a2+mod)%mod); } }