BZOJ 4517: [Sdoi2016]排列计数 错排 + 组合
从 $n$ 个数中选 $m$ 个不错排,那就是说 $n-m$ 个数是错排的.
用组合数乘一下就好了.
Code:
#include <cstdio> #include <algorithm> #define setIO(s) freopen(s".in","r",stdin) using namespace std; namespace IO { char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;} }; typedef long long ll; const int mod=1000000007,N=1000002; ll rev[N],f[N],fac[N],inv[N]; ll qpow(ll base,ll k) { ll tmp=1; for(;k;base=base*base%mod,k>>=1) if(k&1) tmp=tmp*base%mod; return tmp; } ll C(int n,int m) { return fac[n]*inv[m]%mod*inv[n-m]%mod; } int main() { using namespace IO; // setIO("input"); int T=rd(),n,m,i,j; f[1]=0,f[0]=f[2]=1; fac[0]=inv[1]=inv[0]=1; for(i=3;i<N;++i) f[i]=(ll)(i-1)*(f[i-1]+f[i-2])%mod; for(i=1;i<N;++i) fac[i]=fac[i-1]*i%mod,inv[i]=qpow(fac[i],mod-2); for(int cas=1;cas<=T;++cas) { n=rd(),m=rd(); printf("%lld\n",m>n?0:C(n,m)*f[n-m]%mod); } return 0; }