Sdoi2016 排列計數 有關一類錯排問題

2022-09-10 00:24:19 字數 1342 閱讀 8634

乙個經典的問題:有n封信,對於將n個信封全部送錯的方案數。

限制 : - ms   165536 kb

評測說明 : 1s

問題描述

求有多少種長度為 n 的序列 a,滿足以下條件:

1 ~ n 這 n 個數在序列中各出現了一次

若第 i 個數 a[i] 的值為 i,則稱 i 是穩定的。序列恰好有 m 個數是穩定的

滿足條件的序列可能很多,序列數對 10^9+7 取模。

輸入格式

第一行乙個數 t,表示有 t 組資料。

接下來 t 行,每行兩個整數 n、m。

30%資料:t=1000,n≤1000,m≤1000

100%資料:t=100000,n≤1000000,m≤1000000

輸出格式

輸出 t 行,每行乙個數,表示求出的序列數

樣例輸入

51 0

1 15 2

100 50

10000 5000

樣例輸出01

20578028887

60695423

對於這個問題,我們有初始化dp[1] = 0 , dp [2] = 1 (這個還是很顯然),以及dp[0]=1(這個我沒懂為什麼,但必須有,,就類似0!==1的規定),那麼對於這個方程就有dp[i] = (i-1)*(dp[i-1]+dp[i-2])。我們假設i被放在乙個j的位置,那麼這個j如果放在i位置上,答案就是dp[i-2](相當將i-2個數錯排)如果不放在i位置上就等同dp[i-1](將i-1個數錯排)。然後這個i放的j的選擇可以有i-1個,於是就得出方程。

對於本題就等同於求c(n,m)*dp[n-m].即選出m個數,將剩下的錯排。

code:

#include#include#include#include#includeusing namespace std;

const int mod = 1e9+7;

const int maxn = 1000005;

int n,m;

int fac[maxn],inv[maxn],f[maxn];

int add(int x,int y)

int mul(int x,int y)

int ksm(int a,int b)

int main() inv[maxn-5] = ksm(fac[maxn-5],mod-2);

for(int i=maxn-6;i>=0;i--) inv[i]=mul(inv[i+1],i+1);

for(int i=3;i<=maxn-5;i++)

int t; scanf("%d",&t);

while(t--)

}

SDOI 2016 排列計數

題目鏈結 演算法 有m個數在原來的位置上,說明有 n m 個數不再原來的位置上 那麼,我們可以選出 n m 個數,使這 n m 個數都不在原來的位置上,再讓剩下的m個數都在原來的位置上 錯位排列遞推公式 f 1 0 f 2 1 f n n 1 f n 1 f n 2 n 2 因此,答案為c n,n ...

SDOI2016 排列計數

嘟嘟嘟 從今天開始搞一搞組合計數!先學乙個錯排公式。所謂的錯排就是乙個排列,滿足對於任意的 i 有 a i neq i 這東西是可以遞推求的。令 d i 表示長度為 n 的排列的錯排數。我們假設 d n 1 已經求出來,現在考慮第 n 個。首先第乙個肯定要和其中任意第 i 個 1 leqslant ...

SDOI2016 排列計數

求有多少種長度為 n 的序列 a,滿足以下條件 1 n 這 n 個數在序列中各出現了一次 若第 i 個數 a i 的值為 i,則稱 i 是穩定的。序列恰好有 m 個數是穩定的 滿足條件的序列可能很多,序列數對 10 9 7 取模。第一行乙個數 t,表示有 t 組資料。接下來 t 行,每行兩個整數 n...