LG4071 [SDOI2016]排列計數
阿新 • • 發佈:2019-04-05
const ati 個數 pan span 出現 Coding hidden sample
題意
題目描述
求有多少種長度為 n 的序列 A,滿足以下條件:
1 ~ n 這 n 個數在序列中各出現了一次
若第 i 個數 A[i] 的值為 i,則稱 i 是穩定的。序列恰好有 m 個數是穩定的
滿足條件的序列可能很多,序列數對 取模。
輸入輸出格式
輸入格式:第一行一個數 T,表示有 T 組數據。
接下來 T 行,每行兩個整數 n、m。
輸出格式:輸出 T 行,每行一個數,表示求出的序列數
輸入輸出樣例
輸入樣例#1: 復制5 1 0 1 1 5 2 100 50 10000 5000輸出樣例#1: 復制
0 1 20 578028887 60695423
說明
測試點 1 ~ 3: ,,;
測試點 4 ~ 6: ,,;
測試點 7 ~ 9: ,,;
測試點 10 ~ 12:,,;
測試點 13 ~ 14:,,;
測試點 15 ~ 20:,,。
分析
選出哪些元素固定,剩下的就是錯排問題。
錯排數遞推公式:
\[
D_0=1,D_1=0 \D_n=(n-1)(D_{n-1}+D_{n-2}) \quad n\ge 2
\]
答案為
\[
\binom nm D_{n-m}
\]
時間復雜度\(O(n+T)\)
代碼
#include<bits/stdc++.h> #define rg register #define il inline #define co const template<class T>il T read(){ rg T data=0,w=1;rg char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();} while(isdigit(ch)) data=data*10+ch-'0',ch=getchar(); return data*w; } template<class T>il T read(rg T&x) {return x=read<T>();} typedef long long ll; co int N=1e6+1,mod=1e9+7; int num[N]={1,1},inv[N]={1,1},f[N]={1,0}; il int mul(int x,int y){return (ll)x*y%mod;} int main(){ // freopen(".in","r",stdin),freopen(".out","w",stdout); for(int i=2;i<N;++i){ num[i]=mul(num[i-1],i); inv[i]=mul(mod-mod/i,inv[mod%i]); f[i]=mul(i-1,f[i-1]+f[i-2]); } for(int i=2;i<N;++i) inv[i]=mul(inv[i-1],inv[i]); for(int t=read<int>(),n,m;t--;){ read(n),read(m); printf("%d\n",mul(num[n],mul(inv[n-m],mul(inv[m],f[n-m])))); } return 0; }
LG4071 [SDOI2016]排列計數