【組合+錯排】BZOJ4517(Sdoi2016)[排列計數]題解
阿新 • • 發佈:2019-02-10
題目概述
如果
解題報告
其實很簡單……先選出
強制不穩定也就是
錯排遞推公式:
推導:將
然後若
否則就當
示例程式
#include<cstdio>
#include<cctype>
using namespace std;
typedef long long LL;
const int maxn=1000000,MOD=1e9+7;
int te,n,m,fac[maxn+5],INV[maxn+5],D[maxn+5];
#define Eoln(x) ((x)==10||(x)==13||(x)==EOF)
inline char readc()
{
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF;return *l++;
}
inline int readi(int &x)
{
int tot=0,f=1;char ch=readc(),lst='+';
while (!isdigit(ch)) {if (ch==EOF) return EOF;lst=ch;ch=readc();}
if (lst=='-') f=-f;
while (isdigit(ch)) tot=(tot<<3)+(tot<<1)+ch-48,ch=readc();
return x=tot*f,Eoln(ch);
}
void Make()
{
INV[0 ]=INV[1]=1;for (int i=2;i<=maxn;i++) INV[i]=MOD-(LL)(MOD/i)*INV[MOD%i]%MOD;
fac[0]=fac[1]=1;for (int i=2;i<=maxn;i++) fac[i]=(LL)fac[i-1]*i%MOD,INV[i]=(LL)INV[i-1]*INV[i]%MOD;
D[0]=1;D[1]=0;for (int i=2;i<=maxn;i++) D[i]=(LL)(i-1)*(D[i-1]+D[i-2])%MOD;
}
inline int C(int x,int y) {if (x<y) return 0;return (LL)fac[x]*INV[y]%MOD*INV[x-y]%MOD;}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
for (Make(),readi(te);te;te--)
{
readi(n);readi(m);if (n<m) {puts("0");continue;}
printf("%lld\n",(LL)C(n,m)*D[n-m]%MOD);
}
return 0;
}