bzoj2111 perm 排列計數

2022-04-14 04:34:21 字數 1307 閱讀 5966

記憶體限制:512 mib 時間限制:1000 ms 標準輸入輸出

題目描述

稱乙個1,2,...,n的排列p1,p2...,pn是magic的,當且僅當2<=i<=n時,pi>pi/2. 計算1,2,...n的排列中有多少是magic的,答案可能很大,只能輸出模p以後的值

輸入格式

輸入檔案的第一行包含兩個整數 n和p,含義如上所述。

輸出格式

輸出檔案中僅包含乙個整數,表示計算1,2,n的排列中, magic排列的個數模 p的值。

樣例樣例輸入

20 23
樣例輸出

16
資料範圍與提示

100%的資料中,1 ≤  n ≤ 106, p ≤ 10^9,p是乙個質數。 資料有所加強

事實上題目少說一句i為奇數/2就向下取整(雖然說不說都可以推斷,說了比較嚴謹)

既然這樣我們可以把它想象成乙個 二叉堆(小根堆) 滿足magic 就是滿足二叉堆 那麼magic的方案數就是滿足二叉堆的方案數。

但如果暴力計算方式會tle,我們需要用一種別的方式計算

於是就有了樹形dp 設f[i]為以i為根的方案數顯然可以由兩個兒子貢獻過來

當前點因為根是最小的所以size[i]-1表示剩餘的節點數 然後是在size[i]-1的範圍內選size[left]數量的數分配給左兒子

於是

$f[i]=f[(i<<1)]*f[(i<<1|1)]*^}$

由於n比較大然後要用lucas定理

然後注意當前點不能大於n轉移就完了

下面依然是本人醜陋的**

#include#define ll long long

#define a 1100000

#define maxn 1000010

#define p 1000000007

using

namespace

std;

ll m,n,k,f[a],jie[a],ermi[a],ans,ni[a];

inline ll read()

while(isdigit(c))

return f*x;

}ll meng(ll x,ll k)

ll c(ll n,ll m)

void

init()

intmain()

view code

當然也可以線性轉移

for(int i=n;i;--i)

會快很多

bzoj2111 Perm 排列計數

稱乙個1,2,n的排列p1,p2.pn是magic的,當且僅當2 i n時,pi pi 2.計算1,2,n的排列中有多少是magic的,答案可能很大,只能輸出模p以後的值 input 輸入檔案的第一行包含兩個整數 n和p,含義如上所述。output 輸出檔案中僅包含乙個整數,表示計算1,2,的排列中...

bzoj2111 Perm 排列計數 組合數學

一開始以為當i為奇數時不需要pi pi 2,翻了一下題解發現 2是整除。然後這實際上就是求一顆節點數為n的大根堆有多少種。定義f i 為這可樹種以i為根的子樹的方案數,s i 表示子樹的節點數,那麼考慮s i 個數,一定是將最小的給i,剩餘的s i 1 個給左兒子,這s i 1 個可以隨機取,因此共...

Perm排列計數(bzoj2111)

time limit 10 sec memory limit 259 mb submit 2686 solved 811 submit status discuss 稱乙個1,2,n的排列p1,p2 pn是magic的,當且僅當2 i n時,pi pi 2.計算1,2,n的排列中有多少是magic的...