Perm排列計數(bzoj2111)

2021-08-21 15:16:15 字數 1615 閱讀 7974

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

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

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

20 23

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

[ submit][

status][

discuss]

一開始,我很腦抽地領會錯了題目的意思。

我以為那個p(i)>p(i/2)只對偶數管用,根本沒想到i/2可以下去整

於是很快樂地做了乙個小時

又是楊輝三角,又是log表,又是素數

搞得不亦樂乎

結果,當樣例沒過是,我才意識到……

what the f***?

於是,重頭再來(有沒有搞錯,我的時間很寶貴誒)

算了,誰叫我不細心呢

於是我開始重新審視這道題

很容易聯想到二叉樹

因為對於乙個節點i,它下面對應著兩個節點i<<2和i<<2|1

所以,我們很自然地想到數字dp

所以我們設定兩個陣列size和f

f[i]表示以i為根節點的子樹的種類數

顯然最終答案是f[1]

size[i]是指以i為根節點的子樹的節點數

那麼轉移方程就出來了:

f[i]=f[i<<1]*f[i<<1|1]*c(size[i]-1,size[i-1]);

這裡的c(n,m)表示組合數

那麼,接下來的重點,就是這個組合數

給的資料並不小誒

所以,我們就搬出了lucas定理

具體知識點回頭再說

**如下:

#include

#include

#include

using namespace std;

long long n,p;

long long f[2000005],size[2000005];

long long fac[2000005],inv[2000005];

void init()

for(int i=2;i<=n;i++)

for(int i=2;i<=n;i++)

}long long c(long long a,long long b)

if(areturn fac[a]*inv[b]%p

*inv[a-b]%p;

}return c(a%p,b%p)*c(a/p,b/p)%p;

}int main()

printf("%lld",f[1]);

return

0;}

Perm排列計數

記憶體限制 512 mib 時間限制 1000 ms 標準輸入輸出 題目描述 稱乙個1,2,n的排列p1,p2.pn是magic的,當且僅當2 i n時,pi pi 2.計算1,2,n的排列中有多少是magic的,答案可能很大,只能輸出模p以後的值 輸入格式 輸入檔案的第一行包含兩個整數 n和p,含...

Perm 排列計數

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

Perm 排列計數

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