題面
因為每個人只有乙個要求,假如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...