題解 P2606 ZJOI2010 排列計數

2022-05-07 20:48:07 字數 1197 閱讀 4256

題目鏈結

題目大意:求 \(1-n\) 的排列 \(p\) 中,有多少個排列滿足 \(\forall i\in [2,n],p_i > p_\rfloor}\),對給定質數 \(m\) 取模。

分析:

\(p_i > p_\rfloor}\),反過來 \(\forall x,p_x,那麼問題變成一棵 \(n\) 個節點的完全二叉樹,將數 \(1-n\) 分配給每乙個節點,使得每個父節點都比它兩個子節點權值要小的方案數。

進一步,我們不關心數究竟是啥,我們只關心它們之間的相對大小關係。

記 \(siz[u]\) 表示以 \(u\) 為根的子樹大小,\(f[u]\) 表示將 \(siz[u]\) 個互不相同的數分配給以 \(u\) 為根的子樹的合法方案數。記 \(ls,rs\) 為左右兒子。

那麼 \(f[u]=f[ls]\cdot f[rs] \cdot \binom\)

坑點在於,\(n\) 有可能比 \(m\) 大,此時需要使用 \(\text\) 定理

#include using namespace std;

const int maxn = 1e6 + 100;

int n,mod;

inline int add(const int a,const int b)

inline int mul(const int a,const int b)

inline int qpow(int base,int b)

return res;

}inline int inv(const int x)

int fac[maxn];

inline void init()

extern inline int c(const int n,const int m);

inline int lucas(const int n,const int m)

inline int c(const int n,const int m)

int f[maxn << 2],siz[maxn << 2];

#define ls (u << 1)

#define rs (u << 1 | 1)

inline void dp(const int u)

#undef ls

#undef rs

int main()

P2606 ZJOI2010 排列計數 分析

題意可以簡化為用 1,n 的數,組成乙個完全二叉樹,使其滿足小根堆性質,求方案數。令 f i 表示在 i 點的方案數,s i 表示 i 的子節點個數 包括 i 於是得出遞推式 f i c times f times f 由於 bzoj 上 n m 可能 所以需要用 lucas 定理。namespac...

洛谷 2606 ZJOI2010 排列計數

題目描述 稱乙個1,2 n 1,2,n 1,2,n的排列p1,p2.pn p 1,p 2.p n p1 p2 pn 是magic的,當且僅當2 i n 2 i n 2 i n 時,p i pi 2 p i p pi pi 2 計算1,2 n1,2,n 1,2,n的排列中有多少是magic的,答案可能...

P2605 ZJOI2010 基站選址

有n個村莊坐落在一條直線上,第i i 1 個村莊距離第1個村莊的距離為di。需要在這些村莊中建立不超過k個通訊基站,在第i個村莊建立基站的費用為ci。如果在距離第i個村莊不超過si的範圍內建立了乙個通訊基站,那麼就村莊被基站覆蓋了。如果第i個村莊沒有被覆蓋,則需要向他們補償,費用為wi。現在的問題是...