题意:两个集合数量为n,m问第一个集合到第二个集合有多少种合法映射
题解:组合数学的一个模型,n个不同小球装入m个不同的盒子,盒子不为空,答案就是m!*f(n,m),f(n,m)为第二类斯特林数,这里递推会超时,可以考虑容斥,i个盒子为空的方案数为c(m,i)*(m-i)^n然后乘上容斥系数,注意这里的逆元要用O(n)递推,很容易就超时
#include<cstdio> #define ll long long using namespace std; const int maxn=1000005,tt=1e9+7; ll ji[maxn],ans; int n,m,p; ll qsm(ll w,int b){ ll num=1; while(b>0){ if (b%2==1) num=num*w%tt; w=w*w%tt; b>>=1; } return num; } ll c(int x,int y){if (x>y) return x;return ji[y]*qsm(ji[x]*ji[y-x]%tt,tt-2)%tt;} int main(){ ji[0]=1;for (int i=1;i<=1000000;i++) ji[i]=(ji[i-1]*i)%tt; scanf("%d%d",&n,&m); p=1;for (int i=m;i>=1;i--) ans=(ans+c(m-i,m)*qsm(i,n)%tt*p%tt+tt)%tt,p=0-p; printf("%lld ",ans); return 0; }