記憶體限制: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 longview code#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()
當然也可以線性轉移
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的...