bzoj4517[Sdoi2016]排列计数(组合数,错排)
4517: [Sdoi2016]排列计数
Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 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
1 0
1 1
5 2
100 50
10000 5000
Sample Output
0
1
20
578028887
60695423
1
20
578028887
60695423
HINT
Source
/* 水水的组合数+错排 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; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。