正题
题目链接:https://www.luogu.com.cn/problem/P4071
题目大意
每次询问n,mn,mn,m。求有多少个nnn的排列使得ai=ia_i=iai=i的数量恰好为mmm个。
解题思路
首先nnn个之中选择mmm个ai=ia_i=iai=i,选择的方案数为CnmC_{n}^mCnm。剩下的错排就好了
错排推导di=(i−1)(di−1+di−2)d_i=(i-1)(d_{i-1}+d_{i-2})di=(i−1)(di−1+di−2)
所以答案就是Cnm∗dn−mC_n^m*d_{n-m}Cnm∗dn−m
预处理即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+10,XJQ=1e9+7;
ll T,n,m,d[N],fac[N];
ll power(ll x,ll b)
{ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
ll C(ll n,ll m)
{return fac[n]*power(fac[m]*fac[n-m]%XJQ,XJQ-2)%XJQ;}
int main()
{scanf("%lld",&T);d[0]=d[2]=fac[1]=fac[0]=1;fac[2]=2;for(ll i=3;i<=1000000;i++)fac[i]=fac[i-1]*i%XJQ,d[i]=(i-1)*(d[i-1]+d[i-2])%XJQ;while(T--){scanf("%lld%lld",&n,&m);printf("%lld\n",C(n,m)*d[n-m]%XJQ);}
}