P4071 [SDOI2016]排列计数 |排列组合
题目描述
求有多少种 \(1\) 到 \(n\) 的排列 \(a\),满足序列恰好有 \(m\) 个位置 \(i\),使得 \(a_i = i\)。
答案对 \(10^9 + 7\) 取模。
输入格式
本题单测试点内有多组数据。
输入的第一行是一个整数 \(T\),代表测试数据的整数。
以下 \(T\) 行,每行描述一组测试数据。
对于每组测试数据,每行输入两个整数,依次代表 \(n\) 和 \(m\)。
输出格式
共输出 \(T\) 行,对于每组测试数据,输出一行一个整数代表答案。
错排公式\(f[i]=(i-1)(f[i-1]+f[i-2])\)
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=1e9+7,N=1e6+10,M=1e6;
#define int long long
inline int read(){
int x=0; char c=getchar();
while(c<'0'||c>'9')c=getchar();
while('0'<=c&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); }
return x;
}
int jc[N],inv[N],D[N];
inline int ksm(int x,int y){
int res=1;
while(y){
if(y&1)res=res*x%mod;
x=x*x%mod; y>>=1;
}
return res;
}
inline void pre(){
jc[0]=1; for(int i=1;i<=M;i++)jc[i]=jc[i-1]*i%mod;
inv[M]=ksm(jc[M],mod-2);
for(int i=M-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
D[0]=1,D[1]=0,D[2]=1;
for(int i=3;i<=M;i++)D[i]=(i-1)*(D[i-1]+D[i-2])%mod;
}
inline int C(int x,int y){
if(y>x)return 0;
return jc[x]*inv[x-y]%mod*inv[y]%mod;
}
int n,m;
signed main(){
int T=read(); pre();
while(T--){
n=read(),m=read();
printf("%lld\n",C(n,m)*D[n-m]%mod);
}
}
不以物喜,不以己悲