vfk 式名字重排
形式化描述:给定一个长度为N的整数序列A1…N,求有多少种不同长度为的N的整数序列B1…N是A的重排,即可重集{Ai}={Bi}。两个序列不同当且仅当它们任一位置上的元素不相等。
输入
第1行:两个正整数N,k,其中N代表该火星人名字的长度,k代表火星文有多少种字符,我们不妨设在有k种字符的情况下的火星文中的字符分别是0到k−1。
第2行:用空格隔开的N个正整数,代表这个火星人的名字,我们保证这N个数字一定在0到k−1的范围内。
输出
第1行:一个正整数——这个火星人的名字重排方案数对109+7取模的结果(火星人的逻辑特别奇怪,只要知道模数是多少就可以放过你了)。
样例输入
复制样例数据
4 2
0 0 1 1
样例输出
6
提示
满足条件的重排共有如下6种:
0,0,1,1
0,1,0,1
1,0,0,1
0,1,1,0
1,0,1,0
1,1,0,0
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#include <iomanip>
const int M = 1E9+7;
const int maxn = 2e6+5;
const int base = 131;
using namespace std;
const int N=2e6+10;
int a[N];
const int MOD=1e9+7;
ll inv(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%MOD;
a=(a*a)%MOD;
b>>=1;
}
return ans;
}
ll jie[N];
int main(){
int n,m;
jie[1]=1;
for(int i=2;i<=N;i++){
jie[i]=(jie[i-1]*i)%MOD;
}
// for(int i=2;i<=N;i++){
// cout<<jie[i]<<endl;
// }
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
int val;
scanf("%d",&val);
a[val]++;
}
sort(a,a+m,greater<ll>());
ll ans=jie[n];
//cout<<ans<<endl;
for(ll i=0;i<m;i++){
if(a[i]==0)break;
ans=(ans*inv(jie[a[i]],MOD-2))%MOD;
}
printf("%lld\n",ans);
return 0;
}