错排公式
根据题意,要我们求的答案就是C(n,m)*D[n-m];
注意一些小特判,然后因为T很大,我们直接预处理我们所需要的东西,最后直接给答案就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define N 1000005
#define Pi 3.141591653589793238462
#define M(x) memset(x,0,sizeof(x))
#define mod 1000000007
ll D[N],jc[N];
ll ksm(ll a,ll b)//求逆元
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void init()//预处理
{
D[1]=0;D[2]=1;jc[0]=1;
for(ll i=3;i<N;++i)D[i]=(i-1)*(D[i-2]+D[i-1])%mod;//错排公式
for(ll i=1;i<N;++i)jc[i]=jc[i-1]*i%mod;//前N项的阶乘
}
ll C(ll n,ll m)//C(n,m)
{
return jc[n]*ksm(jc[m],mod-2)%mod*ksm(jc[n-m],mod-2)%mod;
}
ll n,m,ans;
int main()
{
init();
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int _=1;cin>>_;
while(_--)
{
cin>>n>>m;
if(n<m)ans=0;
else if(n==m)ans=1;
else ans=D[n-m]*C(n,m)%mod;
cout<<ans<<'\n';
}
return 0;
}