【题解】abc172_e NEQ
abc172_e NEQ
题意
给定 \(n,m\),求有多少组 \(a,b\) 序列满足:
-
\(|a|=|b|=n\)。
-
\(a_i,b_i \in [1,m]\)
-
\(a\) 中元素各不相同。
-
\(b\) 中元素各不相同。
题解
知识点:二项式反演,组合数学,容斥原理。
经典。
设 \(g_k\) 为恰有 \(k\) 位相同的方案数。
设 \(f_k\) 为钦定 \(k\) 位相同,其他随便选的方案数。
所以有,
\[\large \displaystyle f_k=\sum_{i=k}^n \binom{i}{k} \times g_i
\]
二项式反演,
\[\large \displaystyle g_k=\sum_{i=k}^n \binom{i}{k} \times (-1)^{i-k} f_i
\]
根据 \(f_k\) 定义得出,
\[\large \displaystyle f_k=\binom{n}{k} \times A_m^k\times (A_{n-k}^{m-k})^2
\]
答案即为 \(g_0\),此时 \(g_0=\sum_{i=0}^n (-1)^{i} f_i\),退化为了一般的容斥原理。
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()
#define N 502504
#define int long long
const int mod=1e9+7;
int n,m;
namespace comb{
int fac[N],iv[N];
inline int inv(int a){
int ans=1,b=mod-2;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
inline int C(int n,int m){
return fac[n]*iv[n-m]%mod*iv[m]%mod;
}
inline void init(int lim){
fac[0]=1;
rep(i,1,lim){
fac[i]=fac[i-1]*i%mod;
}
iv[lim]=inv(fac[lim]);
per(i,0,lim-1){
iv[i]=iv[i+1]*(i+1)%mod;
}
}
}
inline int neg(int x){
return x&1?-1:1;
}
using comb::C;
using comb::fac;
inline int f(int k){
return C(n,k)*fac[k]%mod*C(m,k)%mod*C(m-k,n-k)%mod*C(m-k,n-k)%mod*fac[n-k]%mod*fac[n-k];
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
comb::init(5e5);
int ans=0;
rep(i,0,n){
ans=(ans+mod+
C(i,0)*neg(i-0)*f(i)%mod
)%mod;
}
cout<<ans;
return 0;
}