https://loj.ac/problem/3044ios
分析:ui
\(f_x=\prod\limits_{t\in child_x}(1-f_t)\)spa
設\(g_x=\prod\limits_{t\in child_x,t\not =s}(1-f_t)\) \(s\)爲\(x\)的重兒子code
那麼\(f_x=(1-f_s)\times g_x\)get
\(=g_x-f_s\times g_x\)
\(\left[ \begin{matrix}-g_x&g_x\\0&1\end{matrix}\right]\times \left[\begin{matrix}f_s\\1\end{matrix}\right]=\left[\begin{matrix}f_x\\1\end{matrix}\right]\)string
容易發現矩陣只須要存左上和右上,用兩個變量維護便可。it
這裏可能須要除\(0\),須要記錄一下非\(0\)部分和\(0\)的數量。io
代碼:class
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <iostream> using namespace std; #define N 200050 #define mod 998244353 #define ls ch[p][0] #define rs ch[p][1] #define db(x) cerr<<#x<<" = "<<x<<endl const int inv2=(mod+1)/2; typedef long long ll; int head[N],to[N<<1],nxt[N<<1],cnt,n,du[N],dep[N],fa[N],L,R,w[N]; int siz[N],lf[N],son[N],sz[N],top[N],val[N],S[N]; ll ans[N],mi[N]; ll qp(ll x,ll y=mod-2) { ll re=1;for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re; } inline void add(int u,int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void df1(int x,int y) { int i; siz[x]=lf[x]; fa[x]=y; sz[x]=1; dep[x]=dep[y]+1; if(dep[x]&1) w[x]=0; else w[x]=n; for(i=head[x];i;i=nxt[i]) if(to[i]!=y) { df1(to[i],x); siz[x]+=siz[to[i]]; sz[x]+=sz[to[i]]; if(dep[x]&1) w[x]=max(w[x],w[to[i]]); else w[x]=min(w[x],w[to[i]]); if(sz[to[i]]>sz[son[x]]) son[x]=to[i]; } if(lf[x]) w[x]=x; val[x]=sz[x]-sz[son[x]]; } struct A { ll x; int t; A() {x=0,t=0;} A(ll x_,int t_) {x=x_,t=t_;} void operator *= (const ll &u) { if(!u) t++; else x=x*u%mod; } void operator /= (const ll &u) { if(!u) t--; else x=x*qp(u)%mod; } operator ll() {return t?0:x;} }; struct Mat { ll l,r; Mat() {} Mat(ll l_,ll r_) {l=l_,r=r_;} Mat operator * (const Mat &u) const { return Mat(l*u.l%mod,(l*u.r+r)%mod); } }I; struct Tree { int ch[N][2],f[N]; A dp[N]; Mat F[N]; int flg,rt; bool isrt(int x) {return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;} void pushup(int p) { F[p]=Mat(-dp[p],dp[p]); if(ls) F[p]=F[ls]*F[p]; if(rs) F[p]=F[p]*F[rs]; } int build(int l,int r) { if(l>r) return 0; int sum=0,i,p,x=0; for(i=l;i<=r;i++) sum+=val[S[i]]; for(i=l;i<=r;i++) { x+=val[S[i]]; if((x<<1)>=sum) break; } p=S[i]; ls=build(l,i-1),rs=build(i+1,r); if(ls) f[ls]=p; if(rs) f[rs]=p; if(!son[p]) { if(flg==0) dp[p].x=(p<w[1]); else dp[p].x=1-(p>w[1]); if(!(dep[p]&1)) dp[p].x=1-dp[p].x; } pushup(p); return p; } int dfs(int rr) { int t,i,x; for(x=rr;x;x=son[x]) { dp[x].x=1; for(i=head[x];i;i=nxt[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) { t=dfs(to[i]); f[t]=x; dp[x]*=(1-F[t].r); } } int tp=0; for(x=rr;x;x=son[x]) S[++tp]=x; return build(1,tp); } void init() { F[0]=I; rt=dfs(1); } void UPD(int p,ll x) { //puts("FUCK"); dp[p]=A(x,0); for(;p;p=f[p]) { if(isrt(p)) dp[f[p]]/=(1-F[p].r); pushup(p); if(isrt(p)) dp[f[p]]*=(1-F[p].r); } } }T0,T1; int main() { I.l=1,I.r=0; scanf("%d%d%d",&n,&L,&R); int i,x,y; for(mi[0]=i=1;i<=n;i++) mi[i]=mi[i-1]*2%mod; for(i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x),du[x]++,du[y]++; for(i=2;i<=n;i++) if(du[i]==1) lf[i]=1; df1(1,0); T0.flg=0,T1.flg=1,T0.init(),T1.init(); //for(i=1;i<=n;i++) db(T0.dp[i]); for(i=1;i<n;i++) { //printf("%lld %lld\n",T0.F[T0.rt].r,T1.F[T1.rt].r); x=w[1]+i-1; if(x>w[1]&&x<=n&&lf[x]) T0.UPD(x,inv2); x=w[1]-i+1; if(x>0&&x<w[1]&&lf[x]) T1.UPD(x,inv2); ll v1=1-T0.F[T0.rt].r,v2=T1.F[T1.rt].r; ans[i]=(mi[siz[1]]-(mi[siz[1]-1])*(v1*v2%mod))%mod; } ans[n]=mi[siz[1]]-1; for(i=R;i>=L;i--) { ans[i]=(ans[i]-ans[i-1])%mod; } for(i=L;i<=R;i++) { printf("%lld ",(ans[i]+mod)%mod); } return 0; }