給定一棵樹,請你回答\(k\in[1,n]\)由\(k\)個點生成出來的虛樹(steiner)的全部方案的大小的和。ios
對於這種分元素而後每一個元素對答案有一個相同的貢獻的計數,通常都是考慮對於一個點考慮對於答案的貢獻。對於一個肯定的\(k\)和一個點\(p\),能夠很輕易的算出\(p\)對於答案的貢獻=\({n\choose k }-( \sum_{u \in Son}siz[u])-(n-siz[p])\)。咱們拿個同記錄相同的組合數的上面的那個數,這個數組設爲\(s_i\)那麼設答案爲\(a_k\),有(\(b_0=0\))
\[ a_k=\sum_{i=0}^n b_i{i\choose k} \]
拆開
\[ a_k=\sum_{i=0} {b_i i!\over k! (i-k)!} \]
隨便化一下
\[ k!a_k=\sum_{i} {(b_ii!)\over (i-k)!} \]
按照上次的那種套路搞出來就能NTT了git
這一發TLE了,不知道爲何......數組
upd: AtCoder 編譯命令沒有-DONLINE_JUDGE
spa
//@winlere #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; typedef long long ll; char __buf[1<<18],*__c=__buf,*__ed=__buf; inline int qr(){ int ret=0,f=0,c=getchar(); while(!isdigit(c))f|=c==45,c=getchar(); while(isdigit(c)) ret=ret*10+c-48,c=getchar(); return f?-ret:ret; } const int maxn=1<<19|1; const int mod=998244353; const int g=3; const int gi=(mod+1)/3; typedef vector<int> poly; poly buk(maxn),c(maxn); int inv[maxn],siz[maxn],r[maxn],jc[maxn],n; inline int MOD(const int&x){return x-mod>=0?x-mod:x;} inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;} inline int MOD(const vector<int>&ve){int ret=1;for(const auto&t:ve) ret=MOD(ret,t); return ret;} inline int ksm(const int&ba,const int&p){ int ret=1; for(int t=p,b=ba;t;t>>=1,b=MOD(b,b)) if(t&1) ret=MOD(ret,b); return ret; } void pre(const int&n){ jc[0]=inv[0]=1; for(int t=1;t<=n;++t) jc[t]=MOD(jc[t-1],t); inv[n]=ksm(jc[n],mod-2); for(int t=n-1;t;--t) inv[t]=MOD(inv[t+1],t+1); for(int t=1;t<=n;++t) if(MOD(jc[t],inv[t])!=1) puts("wa"); } void NTT(poly&a,const int&tag){ static int r[maxn]; int len=a.size(); for(int t=1;t<len;++t) if((r[t]=r[t>>1]>>1|(t&1?len>>1:0))>t) swap(a[t],a[r[t]]); for(int t=1,wn,s=tag==1?g:gi;t<len;t<<=1){ wn=ksm(s,(mod-1)/(t<<1)); for(int i=0;i<len;i+=t<<1) for(int j=0,w=1,p;j<t;++j,w=MOD(w,wn)) p=MOD(a[i+j+t],w),a[i+j+t]=MOD(a[i+j]-p+mod),a[i+j]=MOD(a[i+j]+p); } if(tag!=1) for(int t=0,i=mod-(mod-1)/len;t<len;++t) a[t]=MOD(a[t],i); } poly operator * (poly a,poly b){ int t1=a.size()+b.size()-1,len=1; while(len<t1) len<<=1; a.resize(len); b.resize(len); NTT(a,1); NTT(b,1); for(int t=0;t<len;++t) a[t]=MOD(a[t],b[t]); NTT(a,-1); a.resize(t1); return a; } poly e[maxn]; void add(int fr,int to){ e[fr].push_back(to); e[to].push_back(fr); } void dfs(int now,int last){ siz[now]=1; for(auto t:e[now]) if(t^last) dfs(t,now),++buk[siz[t]],siz[now]+=siz[t]; if(n-siz[now]>=0) ++buk[n-siz[now]]; } int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); //freopen("out.out","w",stdout); #endif n=qr(); buk.resize(n+1); c.resize(n+1); for(int t=1;t<n;++t) add(qr(),qr()); dfs(1,0); pre(2e5); for(int t=0;t<=n;++t) buk[t]=MOD(buk[t],jc[t]); reverse(buk.begin(),buk.end()); for(int t=0;t<=n;++t) c[t]=inv[t]; poly ans=buk*c; ans.resize(n+1); reverse(ans.begin(),ans.end()); for(int t=1;t<=n;++t) printf("%d\n",MOD(MOD({jc[n],inv[t],inv[n-t],n})-MOD(ans[t],inv[t])+mod)); return 0; }