1. 程式人生 > 實用技巧 >多重集合的全排列

多重集合的全排列

多重集合的定義:多重集合不要求元素不能重複。

多重集合表示

\(M=\left \{k_{1}\cdot a_{1},k_{2}\cdot a_{2},\cdots ,k_{n}\cdot a_{n}\right \}\)\(\left ( 其中每個a_{i}代表是不同的元素,每個元素a_{i}有k_{i}個,k_{i}可以是有限數,也可以是∞。\right )\)

多重集的排列:

  • \(多重集合M=\left \{k_{1}\cdot a_{1},k_{2}\cdot a_{2},\cdots ,k_{n}\cdot a_{n}\right \}的r排列數為k^{r}\)
  • \(多重集合M=\left \{k_{1}\cdot a_{1},k_{2}\cdot a_{2},\cdots ,k_{n}\cdot a_{n}\right \}的全排列數為:\frac{\left ( k_{1}+k_{2}+\cdots +k_{n}\right )!}{k_{1}!k_{2}!\cdots k_{n}!}\)

例題:here

題解:

\(n\)個數,選擇\(n-1\)種,那麼有\(C_{n}^{n-1}也就是n種\)方案。對於每種方案,要從\(n-1\)個數裡面,選擇一個重複的數字,有\(n-1\)種方案。此時對於每種方案,長度都是為\(n\)的序列,考慮多重集合的全排列方案數。根據公式可知全排列數為\(\frac{n!}{2!}\),所以題目答案就是:\(n\ast \left ( n-1\right )\ast \frac{n!}{2!}把除以2的階乘轉換為乘以2的階乘的逆元\)

AC_Code:

 1 #include <bits/stdc++.h>
 2 using namespace
std; 3 typedef long long ll; 4 const int maxn = 1e5+10; 5 const ll mod=1e9+7; 6 7 ll F[maxn]; 8 ll n; 9 10 void init(){ 11 F[0]=F[1]=1; 12 for(int i=2;i<=100000;i++) F[i]=1ll*F[i-1]*i%mod; 13 } 14 15 ll qpow(ll a,ll b){ 16 ll res=1; 17 while(b){ 18 if( b&1 ) res = res*a%mod;
19 a = a*a%mod; 20 b>>=1; 21 } 22 return res; 23 } 24 25 int main() 26 { 27 init(); 28 ll t2=qpow(2,mod-2); 29 while( ~scanf("%lld",&n)){ 30 ll ans=n*(n-1)%mod*F[n]%mod*t2%mod; 31 printf("%lld\n",ans); 32 } 33 return 0; 34 }