Description
想知道f:A->B这个函数(其中|A|=n, |B|=m)的所有映射关系要使B的每个元素都要被A的一个元素覆盖到。
数字可能很大你只要输出方案数模1,000,000,007即可。
1<=n,m<=1,000,000
Solution
可以看成n个球放进m个盒子里面,盒子有编号求方案数
那么就是第二类Stirling数*m!
也就是
S(n,m)∗m!=∑mi=0(−1)i∗Cim∗(m−i)n
S
(
n
,
m
)
∗
m
!
=
∑
i
=
0
m
(
−
1
)
i
∗
C
m
i
∗
(
m
−
i
)
n
可以看成是容斥,枚举为0的盒子数量
也可以看成是Stirling数除递推外的另一种求法,即
S(n,m)=1m!∑mi=0(−1)i∗Cim∗(m−i)n
S
(
n
,
m
)
=
1
m
!
∑
i
=
0
m
(
−
1
)
i
∗
C
m
i
∗
(
m
−
i
)
n
Code
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MOD=1000000007;
ll jc[1000001],ny[1000001];
ll ksm(ll x,int dep) {
if (dep==0) return 1;
if (dep==1) return x;
ll tmp=ksm(x,dep/2);
if (dep%2) return tmp*tmp%MOD*x%MOD;
return tmp*tmp%MOD;
}
ll C(ll n,ll m) {
if (n<m) return 0;
if (n==m) return 1;
return jc[n]*ny[m]%MOD*ny[n-m]%MOD;
}
int main(void) {
ll n,m; jc[0]=ny[0]=1;
scanf("%lld%lld",&n,&m);
for (int i=1;i<=max(n,m);i++) {
jc[i]=jc[i-1]*i%MOD;
ny[i]=ksm(jc[i],MOD-2);
}
ll ans=0;
for (int i=0,p=1;i<=m;i++,p*=-1) {
ans+=(C(m,i)*ksm(m-i,n)%MOD*p+MOD)%MOD;
}
ans=(ans+MOD)%MOD;
printf("%lld\n",ans);
return 0;
}