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