2017紀中10 24 合影 樹型DP 組合數學

2021-08-09 18:20:30 字數 1753 閱讀 4455

題面

因為每個人只有乙個要求,假如a要求在b左邊,a就向b連一條邊的話,就是乙個帶環樹。

當然,有環直接無解。所以剩下的是森林。

我們把子樹看成乙個子問題,假如知道了子樹內部的答案如何轉移到父親。設當前轉移x,x的所有子樹都應該安排在x左邊,也就是首先有size[x]-1個空來安排,每安排乙個子樹剩下的空就減一些。安排第乙個兒子c(size[x]-1,size[son1])* ans[son1],第二個(size[x]-size[son1]-1,size[son2])* ans[son2]等等。

為了處理方便,把所有沒有要求的人的父親設為乙個虛根。直接計算改根的答案即可。

其實推出式子答案就是:n!/πsize[i]。

**:

#include

#include

#include

#define ll long long

using namespace std;

const int maxn=200010;

int n,m,mod;

ll jie[maxn],inv[maxn],sz[maxn];

bool vis[maxn],rt[maxn];

struct edge

*con[maxn];

void ins(int

x,int

y)int

read()

returnx;}

ll ksm(ll a,int b) return r;}

ll c(int n,int

m)void dfs(int v)

}ll dp(int v)

return re;

}int main()

for(int i=1;i<=m;i++)

for(int i=1;i<=n;i++)

if(!rt[i]) ins(0,i);

dfs(0);

bool pd=0;

for(int i=1;i<=n;i++) if(!vis[i])

if(pd) puts("0");

else

printf("%lld\n",dp(0));

}return

0;}

推公式**:

#include

#include

#include

#define ll long long

using namespace std;

const int maxn=200010;

int n,m,mod,tot;

ll jie[maxn],inv[maxn],sz[maxn];

bool vis[maxn],rt[maxn];

struct edge

*con[maxn];

void ins(int

x,int

y)int

read()

returnx;}

ll ksm(ll a,int b) return r;}

void dfs(int v)

}int main()

for(int i=1;i<=n;i++)

if(!rt[i]) ins(0,i);

tot=0;

dfs(0);

if(tot<=n) puts("0");

else

}return

0;}

2017紀中10 31 Tree 構造

加入x的子樹都已變白,x為黑的畫,把x和x的所有兒子反色一下就好了。dfs一遍即可。include include using namespace std const int maxn 500010 int n bool c maxn f maxn struct edge con maxn intr...

2017紀中10 31 Calculate 數論

題面 考慮二分答案t。問題轉化成如何高效計算s t 化式子 分開來除,加上他們的餘數和的貢獻。發現ai最大1000,考慮把 ai,bi 按照ai分類,每一類維護cnt,sum,rst 0 ai 1 分別表示數對的個數,bi ai的和,bi ai取值的字首和,那麼對於每乙個ai都可以o 1 計算,對於...

2017紀中11 8 購物 貪心 優先佇列

題面 這題有點像samjia2000出的三元組。考慮把物品按qi從小到大排序,那麼一定有乙個分界點,使得在這個點之前的物品要麼買pi要麼買qi,這個點之後的物品要麼買pi,要麼不買 可以想象一下如果之前有乙個x不買,之後有乙個買qy,買qx不買y一定更優 於是設s i 為使用至多k張優惠券買下1 i...