组合数+错排问题
下面给出错排公式:
$D(n)$表示$n$个数错排
考虑$n$放置的位置为$k$,则$k$的取值有$n-1$种取法
考虑$k$是否放置在第$n$个位置,分别可以转化为$n-1$(不放在 $n$ )与$n-2$(放在 $n$ )的错排问题。
因此,递推公式为$D(n)=(n-1)(D(n-1)+D(n-2))$

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#define gc getchar()
#define ll long long
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
ll p[N],d[N],inv[N];
inline void qr(int &x)
{
    x=0;char c=gc;int f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
    x*=f;
}
void qw(ll x)
{
    if(x<0)x=-x,putchar('-');
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
ll pow_mod(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        b>>=1;a=a*a%mod;
    }
    return ans;
}
int main()
{
    //freopen("a.out","w",stdout);
    inv[0]=1;p[1]=1;inv[1]=1;for(int i=2;i<=1000000;i++)p[i]=p[i-1]*i%mod;
    inv[1000000]=pow_mod(p[1000000],mod-2);
    for(int i=999999;i>=2;i--)inv[i]=inv[i+1]*(i+1)%mod;
    d[1]=0;for(int i=2;i<=1000000;i++)d[i]=(d[i-1]*i%mod+((i&1)?-1:1)+mod)%mod;
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,m;qr(n),qr(m);
        //if(m==0){puts("0");continue;}
        ll ans=p[n]*inv[m]%mod*inv[n-m]%mod;
        if(n-m)ans=ans*d[n-m]%mod;qw(ans);puts("");
    }
    return 0;
}