YbtOJ#20081-[NOIP2020模拟赛B组Day8]树上排列【组合数,树形dp】
生活随笔
收集整理的這篇文章主要介紹了
YbtOJ#20081-[NOIP2020模拟赛B组Day8]树上排列【组合数,树形dp】
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題面鏈接:https://www.ybtoj.com.cn/contest/62/problem/3
題目大意
nnn個(gè)點(diǎn)的一棵樹(shù),每個(gè)邊的邊會(huì)表示一個(gè)大小關(guān)系(如px>pyp_x>p_ypx?>py?或px<pyp_x<p_ypx?<py?)。求有多少個(gè)排列滿足所有條件。
解題思路
考慮樹(shù)形dpdpdp,設(shè)fi,jf_{i,j}fi,j?表示點(diǎn)iii的子樹(shù)中有jjj個(gè)比他小的數(shù)字時(shí)的方案數(shù)。
那么如果有條件py<pxp_y<p_xpy?<px?考慮如何轉(zhuǎn)移,我們枚舉一下i,ji,ji,j表示之前比iii小的數(shù)的個(gè)數(shù)和yyy里面比xxx小的個(gè)數(shù),然后再枚舉一個(gè)kkk表示yyy里面比yyy小的數(shù)的個(gè)數(shù)。
然后用組合數(shù)插板表示方案,發(fā)現(xiàn)這樣是O(n3)O(n^3)O(n3)的,發(fā)現(xiàn)kkk可以前/后綴和優(yōu)化,所以可以縮掉,時(shí)間復(fù)雜度為O(n2)O(n^2)O(n2)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=5100,XJQ=998244353; struct node{ll to,next,w; }a[N*2]; ll n,tot,ls[N],c[N][N],f[N][N],g[N],siz[N],ans; ll C(ll n,ll m){return c[n+1][m+1];} void addl(ll x,ll y,ll w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;return; } void dfs(ll x,ll fa){f[x][0]=1;siz[x]=1;for(ll p=ls[x];p;p=a[p].next){ll y=a[p].to;if(y==fa)continue;dfs(y,x);for(ll i=0;i<=siz[x]+siz[y];i++)g[i]=0;if(a[p].w){for(ll i=0;i<siz[x];i++){ll tmp=0;for(ll j=siz[y]-1;j>=0;j--){ll px=i,py=j;tmp=(tmp+f[y][j])%XJQ;ll sx=siz[x]-i-1,sy=siz[y]-j-1;(g[siz[x]+siz[y]-sx-sy-2]+=f[x][i]*tmp%XJQ*C(sx+sy+1,sx)%XJQ*C(px+py,py)%XJQ)%=XJQ;}}}else{for(ll i=0;i<siz[x];i++){ll tmp=0;for(ll j=0;j<siz[y];j++){ll px=i,py=j;tmp=(tmp+f[y][j])%XJQ;ll sx=siz[x]-i-1,sy=siz[y]-j-1;(g[px+py+1]+=f[x][i]*tmp%XJQ*C(px+py+1,px)%XJQ*C(sx+sy,sy)%XJQ)%=XJQ;}}}siz[x]+=siz[y];for(ll i=0;i<=siz[x];i++)f[x][i]=g[i];}return; } int main() {freopen("perm.in","r",stdin);freopen("perm.out","w",stdout);scanf("%lld",&n);for(ll i=1;i<n;i++){ll x,y;scanf("%lld%lld",&x,&y);addl(x,y,0);addl(y,x,1);}c[0][0]=1;for(ll i=1;i<N;i++)for(ll j=1;j<N;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%XJQ;dfs(1,1);for(ll i=0;i<siz[1];i++)(ans+=f[1][i])%=XJQ;printf("%lld\n",ans); } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的YbtOJ#20081-[NOIP2020模拟赛B组Day8]树上排列【组合数,树形dp】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 什么是pid调节器
- 下一篇: 翡翠怎么看 翡翠如何鉴别