目录
題目
題目給定一個n,你需要對n個P和n個D求出可能排列數。
P和D都有編號。
排列的規則為,要先放置Pi後才可以放置Di,D的位置沒有限定。
Method 1 Permutation
利用高中學的排列知識就可以解決了。
P1_P2_P3_P4_D2_D3_D4_
我們假設P一開始都已經放好了,他總共站了n個位置,那麼他的排序數是
好了處理了P,我們來想一下D怎麼放置,他可以選擇插進P和P之間或者直接在P的後面放置
那麼他總共有多少總選擇呢。
我們來模擬一下,看看D1可以放的位置
P1 _ P2 _ P3 _ P4 _ D2 _ D3 _ D4 _
P1 D1 P2 _ P3 _ P4 _ D2 _ D3 _ D4 _
P1 _ P2 D1 P3 _ P4 _ D2 _ D3 _ D4 _
.....
D1可以選擇放在P1後面或者不放,2*n - 1的選擇
那麼我們來看看D2的有多少種可能
P1 _ P2 _ P3 _ P4 _D1_D3_D4_
P1 _ P2 D2 P3 _ P4 _D1_D3_D4_
P1 _ P2 _ P3 D2 P4 _D1_D3_D4_
.....
由於D2只能放在p2之後,亦他的可能性要減去p1和p2佔掉的位置,還有D1的位置,所以總共的可能性為2n - 3 = 2(n - 1) - 1
對於D3同樣的規律可以套用,那麼他的可能性為,p1,p2,p3,D1,D2,要減掉所以只有
2n - 5 = 2(n-2) - 1
你很快發現規律,每次都是減掉1,3,5,7,9,11並且順著過去,那麼我們可以嘗試找到通式
最後答案為
剩下就是模擬了,簡單到沒朋友。
class Solution {
private:
long long mod = 1e9 + 7;
public:
int countOrders(int n) {
if(n == 1)return 1;
long long res = 1;
for(int i = 0; i <= n - 1; i++){
if(i > 0) (res *= i) %= mod;
(res *= (2*(n - i) - 1)) %= mod;
}
(res *= n) %= mod;
return res;
}
};
Method 2 Permutation and Set
思路:把不合法情況剔除,只留下合法的情況。
總放置方案:
我們現在考慮不合法的情況
對於任意的一個 Pi 他的 Di 都應該在他的右邊否則都是非法情況。
順著下去,我們可以得知,在總方案數中Pi會有相同機會出現在任何位置,並且Di也是,我們可以直接肯定對於一個 Pi 而言,非法情況佔據一半,合法情況佔據一半。
總共有 n 個 P,所以總方案數要除以 2^n
long ans = 1;
int MOD = 1e9 + 7;
int countOrders(int n) {
for (int i = 1; i <= 2 * n; ++i) {
ans = ans * i;
if (i % 2 == 0) {
ans = ans / 2;
}
ans %= MOD;
}
return ans;
}