题目链接:https://loj.ac/problem/2034
挺基础的错排题目
附错排资料:
https://baike.baidu.com/item/错排公式/10978508?fr=aladdin
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e6+5; const int MOD=1e9+7; ll dp[MAXN]; ll fac[MAXN]; ll qpow(ll a,ll b) { ll ans=1;a%=MOD; for(ll i=b;i;i>>=1,a=a*a%MOD) if(i&1)ans=ans*a%MOD; return ans; } ll C(ll n,ll m) { if(m>n||m<0)return 0; ll s1=fac[n],s2=fac[n-m]*fac[m]%MOD; return s1*qpow(s2,MOD-2)%MOD;//费马小定理求逆元 } void init() { fac[0]=1; for(int i=1;i<MAXN;i++)//阶乘打表 fac[i]=fac[i-1]*i%MOD; dp[0]=1;dp[1]=0;dp[2]=1; for(int i=3;i<MAXN;i++) { dp[i]=1LL*(i-1)*(dp[i-1]+dp[i-2])%MOD; } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); if(m>n) printf("0\n"); else printf("%lld\n",C(n,m)*dp[n-m]%MOD); } return 0; }