bzoj4714 旋轉排列

2022-05-01 06:18:08 字數 1479 閱讀 6790

time limit: 20 sec  memory limit: 512 mb

submit: 74  solved: 46

[submit][status][discuss]

輸入僅有一行,包含乙個整數n,1≤n≤500000

輸出一行,包含乙個整數,代表答案。49

【樣例解釋】

k=2時的方案數為3,k=4時的方案數為6,k=1和k=3時的答案為0。

當k=2時,合法的排列有、和。

分析:挺難的一道數學題.

先列舉k.然後求包含長度為k的迴圈節的排列的數量. 直接c(n,k)是不行的,會出現下面這種情況:

,兩個長度為k的迴圈節. c(n,k)會先把第乙個迴圈節給算進去,然後會把第二個迴圈節算進去,它們就成了兩種不同的方案,事實上它們是同一種方案.

為什麼會這樣呢?因為選長度為k的迴圈節不僅僅要考慮到它的長度為k,還要考慮到選了多少個. 而選了多少個是不好控制的,所以我們考慮選了至少多少個,用容斥原理來算即可.

,列舉i表示選了多少個. 大致的原理就是:先選乙個,那麼就佔據了k個位置,只能從剩下的n - k個位置中選k個.這是上面組合數的意義. 下面為什麼要除以乙個階乘呢?因為用組合數分步計算方案數考慮了迴圈節的位置.

,這種情況下會被算兩次. 事實上它們只應該被算一次. 因為迴圈節的本質是一樣的,我們只考慮它的個數. 所以要除以全排列數.(排列-->組合,有序-->無序).

分析完了選迴圈節的方案數,那麼迴圈節裡面的方案數該怎麼確定呢?對於乙個為k的迴圈節. 固定第乙個元素. 那麼第二個元素就只有k-1個位置可選,第三個元素只有k-2個位置可選,以此類推,方案數為(k-1)!

迴圈節外面的方案數要怎麼確定?這些數唯一的限制就是ai != i. 錯位排列計算一下就好了.

#include #include 

#include

#include

using

namespace

std;

typedef

long

long

ll;const ll mod = 1e9+7,maxn = 500010

;ll n,ans,d[maxn],jie[maxn],ni[maxn],nijie[maxn];

ll c(ll x,ll y)

intmain()

for (ll k = 2; k <= n; k++)

else

}ans +=temp;

if (ans >=mod)

ans -=mod;

}printf(

"%lld\n

",ans);

return0;

}

BZOJ4714 旋轉排列

就是對於每個錯排,統計裡面有多少種環長 考慮列舉環長l,可以用容斥計算不含長為l的環的方案數cl c l,總數減去cl c l就是貢獻 cl n l i 0 nil ij 2 jl 1l 1 l 1 i c l i 0 n l i ln j 2i l 1 jl 1 l 1 i 柿子大概長這樣 預處理...

BZOJ4714 旋轉排列

對於每個 k 問題等價於求有多少置換滿足 1.存在乙個迴圈長度為 k 2.任意乙個迴圈長度 geq 2 列舉這種環的個數 t 設 g t 表示至少有 kt 個人分成 t 個長度為 k 的迴圈的方案數,考慮列舉第乙個人和哪些人分在了一起,同時有 k 1 種可能的環,有 g t c kt 1,k 1 g...

LintCode 搜尋旋轉排列陣列

題目 假設有乙個排序的按未知的旋轉軸旋轉的陣列 比如,0 1 2 4 5 6 7 可能成為4 5 6 7 0 1 2 給定乙個目標值進行搜尋,如果在陣列中找到目標值返回陣列中的索引位置,否則返回 1。你可以假設陣列中不存在重複的元素。樣例 給出 4,5,1,2,3 和target 1,返回 2 給出...