题目链接:https://atcoder.jp/contests/abc172/tasks/abc172_e
题意:从 m m m个数中选择分别选择 n n n个数组合成两个序列 A , B A,B A,B,满足 A i ! = B i A_i != B_i Ai!=Bi且每个序列都没有相同的数,问这样的序列一共有多少对。
思路:首先,我们可以考虑从
m
m
m个数里面选择
n
n
n个数,一共可以组成多少个序列,答案就是
A
m
n
A_m^n
Amn,这样就相当于确定了
A
A
A序列的个数。这样我们就可以知道
B
B
B序列的个数就是从
m
m
m个数里选择
n
n
n个数,其中第
i
i
i个数不为
i
i
i的序列个数。
那该怎么求呢?这时候就可以用容斥原理啦!
第
i
i
i个数不为
i
i
i的并集和 = 总数 - 一个数不为
i
i
i + 两个数不为
i
i
i - 三个数不为
i
i
i + …
这样答案就出来啦,具体实现详见代码。
AC代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <string>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define pii pair<int,int>
#define sd(x) scanf("%d",&x)
#define slld(x) scanf("%lld",&x)
#define pd(x) printf("%d\n",x)
#define plld(x) printf("%lld\n",x)
#define rep(i,a,b) for(int i = (a) ; i <= (b) ; i++)
#define per(i,a,b) for(int i = (a) ; i >= (b) ; i--)
#define mem(a) memset(a,0,sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define fast_io ios::sync_with_stdio(false)
const LL mod = 1e9 + 7;
const int maxn = 5e5 + 7;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);
LL f[maxn],inv[maxn];
void init() {
inv[0] = f[0] = inv[1] = f[1] = 1;
for(LL i = 2 ; i <= maxn ; i++) {
inv[i] = ((mod - mod / i) * inv[mod%i]) % mod;
f[i] = i;
}
for(LL i = 2 ; i <= maxn ; i++) {
inv[i] = (inv[i] * inv[i-1]) % mod;
f[i] = (f[i] * f[i-1]) % mod;
}
}
LL C(LL x,LL y) {
return f[x] * inv[y] % mod * inv[x-y] % mod;
}
LL A(LL x,LL y) {
return f[x] * inv[x-y] % mod;
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
long _begin_time = clock();
#endif
init();
int n,m;
sd(n),sd(m);
LL ans = A(m,n);
for(LL i = 1 ; i <= n ; i++) {
LL res = C(n,i) * A(m - i , n - i) % mod;
if(i&1) ans = (ans - res + mod) % mod;
else ans = (ans + res) % mod;
}
ans = ans * A(m,n) % mod;
plld(ans);
#ifndef ONLINE_JUDGE
long _end_time = clock();
// cout << "time = " << _end_time - _begin_time << endl;
#endif
return 0;
}