洛谷 2606 ZJOI2010 排列計數

2021-09-28 23:26:00 字數 1864 閱讀 1893

題目描述

稱乙個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的,答案可能很大,只能輸出模p以後的值

輸入格式

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

輸出格式

輸出檔案中僅包含乙個整數,表示計算1,2

,⋯,n

1,2,⋯, n

1,2,⋯,

n的排列中, magic排列的個數模 p

pp的值。

輸入輸出樣例

輸入 #1

20 23

輸出 #1

16

說明/提示

100

100%

100的資料中,1≤n

≤106

,p≤1

09,p

1 ≤n ≤ 10^6, p≤ 10^9,p

1≤n≤10

6,p≤

109,

p是乙個質數。

解釋:由p

i>pi

/2

p_i>p_

pi​>pi

/2​性質,我們可以畫出拓撲結構,大約和完全二叉樹是一樣的,所以我們可以先dp出,滿完全二叉樹,的全排列組合數即dp[

i]=d

p[i−

1]2∗

c2i−

22i−

1−

1dp[i]=dp[i-1]^2*c_^-1}

dp[i]=

dp[i

−1]2

∗c2i

−22i

−1−1

​,其中i

ii為高度為i

ii,然後我們可以遞迴的分解樹,每碰到乙個滿完全二叉樹,就直接返回dp[

i]

dp[i]

dp[i

]

#includeusing namespace std;

long long fact[2000003]=;

long long n=0,p=1000000009;

long long pow(long long a,long long b)

return ret;

}long long dp[30]=;

long long mi=8;

long long c(long long n,long long m)

int check(int x)

if(sum<=1) return num-1;

else return 0;

}long long ok(int n)else

return c(n-1,b)*ok(a)%p*ok(b)%p;

}int main()

cout

}

題解 P2606 ZJOI2010 排列計數

題目鏈結 題目大意 求 1 n 的排列 p 中,有多少個排列滿足 forall i in 2,n p i p rfloor 對給定質數 m 取模。分析 p i p rfloor 反過來 forall x,p x,那麼問題變成一棵 n 個節點的完全二叉樹,將數 1 n 分配給每乙個節點,使得每個父節點...

P2606 ZJOI2010 排列計數 分析

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

洛谷P2602 ZJOI2010 數字計數 題解

很裸的一道數字dp的板子 定義f 當前列舉到的數字 當前數字之前的答案 列舉的數字 其它的套板子就可以了,要注意一下字首0的判斷 1 include2 include3 include4 include5 include6 include7 using namespace std 8 typedef...