SDOI2016排列计数


[ans=C^m_nD_{n-m} ]

D为错排

[D_1=0,D_2=1,D_n=(n-1)*(D_{n-1}+D_{n-2}) ]

[D_n=nD_{n-1}+(-1)^{n-2} ]

[D_n=n!(1-frac 1{1!}+frac 1{2!}-frac 1{3!}+…+(-1)^nfrac 1{n!}) ]

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=1e6+4,mod=1e9+7;
inline int ksm(int x,int r){
	int ret=1;
	for(int i=0;(1<<i)<=r;i++){
		if((r>>i)&1)ret=ret*x%mod;
		x=x*x%mod;
	}
	return ret;
}
int fac[N],inv[N],d[N];
inline void pre(){
	fac[0]=fac[1]=inv[0]=inv[1]=d[2]=d[0]=1;
	for(int i=2;i<N;i++)fac[i]=fac[i-1]*i%mod;
	inv[N-1]=ksm(fac[N-1],mod-2);
	for(int i=N-2;i>1;i--)inv[i]=inv[i+1]*(i+1)%mod;
	for(int i=3;i<N;i++)d[i]=(i-1)*(d[i-1]+d[i-2])%mod;
}
signed main(){
	pre();
	int T=read(),n,m;
	while(T--){
		n=read();m=read();
		cout<<fac[n]*inv[m]%mod*inv[n-m]%mod*d[n-m]%mod<<"
";
	} 
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12560260.html