多重集合的全排列
多重集合的定义:多重集合不要求元素不能重复。
多重集合表示:
\(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 }