E - NEQ(容斥原理&组合数学)

传送门

思路:容斥原理+组合数学。

显然要求且数组中元素互异。

所以对于数组,我们要从个数选个数来全排列。

即个数为.

接下来我们考虑每个对于的方案,对于有多少个。

显然这是个一个容斥原理的应用,我们考虑用总方案减去所有不合法的方案数,

枚举不合法的位置个数分别为个对应的方案数,

当不合法的位置有个时,不合法的方案数为:

个位置中选出个不合法的位置,然后用剩下个数,选出个数进行全排列。

然后用

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int n,m;
ll fac[N],inv[N];
ll ksm(ll a,ll n){
    ll ans=1;
    while(n){
        if(n&1) ans=ans*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans;
}
ll C(int m,int n){
    return fac[m]*inv[m-n]%mod*inv[n]%mod;
}
ll A(int m,int n){
    return fac[m]*inv[m-n]%mod;
}
int main(){
    scanf("%d%d",&n,&m); 
    fac[0]=1;
    for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;//阶乘递推. 
    inv[m]=ksm(fac[m],mod-2);//费马小定理. 
    for(int i=m-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;//阶乘逆元递推. 
    ll ans=0;
    for(int i=0;i<=n;i++){
        ans+=C(n,i)*((i&1)?-1:1)*A(m-i,n-i)%mod;
    }
    ans=(ans%mod+mod)%mod;
    printf("%lld\n",ans*A(m,n)%mod);
    return 0;
}