首先需要了解错排公式:
D(n) = (n-1)*(D(n-1)+D(n-2) )
D(n) 即为n个数1-n进行排列,每个人的下标都不能等于自己的情况数量。
然后这题就很显然了,公式为:
C
n
m
×
D
(
n
)
C_n^m \times D(n)
Cnm×D(n)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
const int mod = 1e9+7;
const int N = 1e6+5;
int f[N],inv[N],d[N];
ll ksm(ll x,ll y){//注意开long long
ll a = 1,base = x;
while(y){
if(y & 1) a = (a * base) % mod;
base = (base * base) % mod;
y >>= 1;
}
return a % mod;//拼命mod
}
void init()
{
f[0] = 1;
for(int i=1;i<=1e6;i++)
{
f[i] = f[i-1]*i%mod;
inv[i] = ksm(f[i],mod-2);
}
d[0] = 0,d[1] = 0,d[2]=1;
for(int i=3;i<=1e6;i++)
{
d[i] = (i-1)*(d[i-1]+d[i-2])%mod;
}
}
signed main()
{
int t;
scanf("%lld",&t);
init();
while(t--)
{
int n,m;
scanf("%lld%lld",&n,&m);
if (n - m == 1) printf("0\n");
else if (m == n) printf("1\n");
else if (m == 0) printf("%lld\n",d[n]);
else {
printf("%lld\n",f[n] * inv[m] % mod * inv[n-m] % mod * d[n-m] % mod);
}
}
}