多重集合的全排列

多重集合的定义:多重集合不要求元素不能重复。

多重集合表示

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

多重集的排列:

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

 例题:here

 题解:

(n)个数,选择(n-1)种,那么有(C_{n}^{n-1}也就是n种)方案。对于每种方案,要从(n-1)个数里面,选择一个重复的数字,有(n-1)种方案。此时对于每种方案,长度都是为(n)的序列,考虑多重集合的全排列方案数。根据公式可知全排列数为(frac{n!}{2!}),所以题目答案就是:(nast left ( n-1 ight )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
",ans);
32     }
33     return 0;
34 }
原文地址:https://www.cnblogs.com/wsy107316/p/13320745.html