1. 程式人生 > >bzoj4517[Sdoi2016]排列計數(組合數,錯排)

bzoj4517[Sdoi2016]排列計數(組合數,錯排)

4517: [Sdoi2016]排列計數

Time Limit: 60 Sec  Memory Limit: 128 MB
Submit: 1792  Solved: 1111
[Submit][Status][Discuss]

Description

求有多少種長度為 n 的序列 A,滿足以下條件: 1 ~ n 這 n 個數在序列中各出現了一次 若第 i 個數 A[i] 的值為 i,則稱 i 是穩定的。序列恰好有 m 個數是穩定的 滿足條件的序列可能很多,序列數對 10^9+7 取模。

Input

第一行一個數 T,表示有 T 組資料。 接下來 T 行,每行兩個整數 n、m。 T=500000,n≤1000000,m≤1000000  

Output

輸出 T 行,每行一個數,表示求出的序列數

 

Sample Input

5
1 0
1 1
5 2
100 50
10000 5000

Sample Output

0
1
20
578028887
60695423

HINT

 

Source

鳴謝Menci上傳

 

/*
水水的組合數+錯排 
C(n,m)*D[n-m]
tm bzoj為什麼還是CE!! 
*/ #include<bits/stdc++.h> #define N 1000002 #define M 1000000007 using namespace std; int n,m; long long inv[N]={1,1},fac[N]={1,1},f[N]={1,1},D[N]; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='
9'){x=x*10+c-'0';c=getchar();} return x*f; } inline int C(int a,int b) { return ((fac[a]*inv[b])%M*inv[a-b]%M)%M; } inline void init() { fac[1]=1; for(int i=2;i<=N;i++) { fac[i]=(1ll*fac[i-1]%M*i)%M; f[i]=((M-M/i)*f[M%i])%M; inv[i]=(inv[i-1]*f[i])%M; } } int main() { //freopen("ly.in","r",stdin); D[0]=1;D[2]=1;init(); for(int i=3;i<=N;i++) D[i]=((i-1)*(D[i-1]%M+D[i-2]%M))%M; int T;cin>>T; while(T--) { n=read();m=read(); if (n-m==1) printf("0\n"); else if(m==n) printf("1\n"); else if(m==0) cout<<D[n]<<endl; else cout<<(1ll*C(n,m)*D[n-m])%M<<endl; } return 0; }