hdu5279 YJC plays Minecraft

\(n\)个点的有标号树总共有\(n^{n-2}\)
\(f[i]\)表示\(i\)个点有标号森林个数
枚举一号点所在树大小 有

\[f[n]=\sum_{i=1}^n\binom{n-1}{i-1}i^{i-2}f[n-i] \]

可以通过分治fft解决
其实也完全可以用EGF的语言叙述 比如如果令\(T(x)\)\(i\)个点有标号树个数的EGF 那么\(F(x)=\exp T(x)\) 只不过我过于不熟练
考虑将每个部分的\(f[a[i]]\)乘起来 环上的边自由选择即乘上\(2^n\)
但这样最终答案多算了一个不合法的情况:所有环上的边都被选择且每个块的一号点与\(a[i]\)号点连通
\(g[i]\)表示\(i\)个点有标号生成森林且满足一号点与\(i\)号点连通方案数
还是枚举一号点与\(i\)号点所在树 有

\[g[n]=\sum_{i=2}^{n}\binom{n-2}{i-2}i^{i-2}f[n-i] \]

\[ans=2^n\times\prod_i f[a[i]]-\prod_i g[a[i]] \]

又一次为了偷懒写成\(O(n\log^2 n)\)

#include
using namespace std;
#define fp(i,l,r) for(register int (i)=(l);i<=(r);++(i))
#define fd(i,l,r) for(register int (i)=(l);i>=(r);--(i))
#define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
#define mem(a) memset((a),0,sizeof (a))
#define O(x) cerr<<#x<<':'<=10)wr(x/10);
    putchar('0'+x%10);
}
const int MAXN=280000,mod=998244353;
int t1[MAXN],t2[MAXN],tr[MAXN],lim,GG[MAXN],gg[MAXN];
int F[MAXN],G[MAXN],tot,fac[MAXN],ifac[MAXN],pw[MAXN];
inline void tmod(int &x){x%=mod;}
inline void rmod(int &x){x+=x>>31&mod;} 
inline int qpow(int a,int b){
    int res=1;
    for(;b;b>>=1,tmod(a*=a))
    if(b&1)tmod(res*=a);
    return res;
}
inline int ginv(int x){return qpow(x,mod-2);}
inline void ntt(int a[],bool flag){
    fp(i,0,lim-1)if(i>1]>>1)|(i&1?lim>>1:0);
}
void dac(int l,int r){
    if(r-l==1){F[l]=(l?F[l]*fac[l-1]%mod:1);return;}
    int mid=l+r>>1;dac(l,mid);
    lim=r-l;
    fp(i,0,lim-1)tr[i]=(tr[i>>1]>>1)|(i&1?lim>>1:0);
    t1[0]=0;fp(i,1,r-l-1)tmod(t1[i]=pw[i]*ifac[i-1]);
    fp(i,0,mid-l-1)tmod(t2[i]=ifac[i+l]*F[i+l]);fp(i,mid-l,lim-1)t2[i]=0;
    ntt(t1,0);ntt(t2,0);
    fp(i,0,lim-1)tmod(t1[i]*=t2[i]);
    ntt(t1,1);
    fp(i,mid,r-1)rmod(F[i]+=t1[i-l]-mod);dac(mid,r);
}
inline void prework(int n){
    fac[0]=pw[1]=1;
    fp(i,1,n+2)tmod(fac[i]=fac[i-1]*i);ifac[n+2]=ginv(fac[n+2]);
    fd(i,n+1,0)tmod(ifac[i]=ifac[i+1]*(i+1));
    fp(i,2,n+2)pw[i]=qpow(i,i-2);
    for(tot=1;tot<=n;tot<<=1);dac(0,tot);
    t1[0]=t1[1]=0;getlim(2*n);
    fp(i,2,n)tmod(t1[i]=ifac[i-2]*pw[i]);fp(i,n+1,lim-1)t1[i]=0;
    fp(i,0,n)tmod(t2[i]=F[i]*ifac[i]);fp(i,n+1,lim-1)t2[i]=0;
    ntt(t1,0);ntt(t2,0);
    fp(i,0,lim-1)tmod(G[i]=t1[i]*t2[i]);
    ntt(G,1);
    fp(i,2,n)tmod(G[i]*=fac[i-2]);
    G[1]=1;
}
inline void solve(){
    int n=read(),res1=qpow(2,n),res2=1;
    fp(i,1,n){
        int x=read();tmod(res1*=F[x]);tmod(res2*=G[x]);
    }
    printf("%lld\n",(res1-res2+mod)%mod);
}
main(){
    GG[0]=1;GG[1]=qpow(3,(mod-1)/(1<<18));
    fp(i,2,MAXN-1)tmod(GG[i]=GG[i-1]*GG[1]);prework(100000);
    int tt=read();
    while(tt--)solve();
    return 0;
}

你可能感兴趣的:(hdu5279 YJC plays Minecraft)