容斥+组合数学——atcoder abc172 E

/*
对于A的任何一种排列
  设B至少i个位置和A相同:C(n,i)*A(m-i,n-i)
对上面那个容斥下就行
*/ #include<bits/stdc++.h> using namespace std; #define ll long long #define mod 1000000007 #define N 500005 ll n,m,ans; ll F[N], Finv[N], inv[N];///F是阶层 Finv是逆元的阶层 void init(){ inv[1] = 1; for(int i = 2; i < N; i++) inv[i] = (mod - mod/i) * 1ll * inv[mod % i] % mod; F[0] = Finv[0] = 1; for(int i = 1; i < N; i++){ F[i] = F[i-1] * 1ll * i % mod; Finv[i] = Finv[i-1] * 1ll * inv[i] % mod; } } int C(int n, int m){ if(m < 0 || m > n) return 0; return F[n] * 1ll * Finv[n-m] % mod * Finv[m] % mod; } int main(){ cin>>n>>m; init(); ans=C(m,n)*F[n]%mod; for(int i=1;i<=n;i++){ ll flag=(i%2)?-1:1; ll tmp = C(n,i); tmp = tmp*C(m-i,n-i)%mod; tmp = tmp*F[n-i]%mod; ans=(ans+flag*tmp+2*mod)%mod; } cout<<ans*C(m,n)%mod*F[n]%mod<<'\n'; }

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/13200320.html