先考虑怎样求出
1
到
先考虑
Dn
的容斥求法:
Dn=Ann−An−1n+An−2n−An−3n+...+(−1)nA0n
。
把
A
化为阶乘形式后,利用分配律可以得到
1、
D0=1
2、当
i
是奇数时,
3、当
i
是偶数时,
回到原问题。可以发现,如果固定了满足
i=A[i]
的
m
个位置,那么剩下的
所以答案
=Cmn∗Dn−m
。预处理阶乘,阶乘逆元和
D
之后就可以
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int MaxN = 1e6, N = MaxN + 5, PYZ = 1e9 + 7;
int n, m, A[N], D[N], inv[N];
int qpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = 1ll * res * a % PYZ;
a = 1ll * a * a % PYZ;
b >>= 1;
}
return res;
}
int C(int n, int m) {
return 1ll * A[n] * inv[m] % PYZ * inv[n - m] % PYZ;
}
void init() {
int i; A[0] = D[0] = 1; for (i = 1; i <= MaxN; i++) {
A[i] = 1ll * A[i - 1] * i % PYZ;
D[i] = (1ll * D[i - 1] * i + (i & 1 ? -1 : 1)) % PYZ;
if (D[i] < 0) D[i] += PYZ;
}
inv[MaxN] = qpow(A[MaxN], PYZ - 2);
for (i = MaxN - 1; i >= 0; i--)
inv[i] = 1ll * inv[i + 1] * (i + 1) % PYZ;
}
void work() {
n = read(); m = read();
printf("%d\n", 1ll * C(n, m) * D[n - m] % PYZ);
}
int main() {
init(); int T = read();
while (T--) work();
return 0;
}