組合數取模的題

2022-08-21 21:39:08 字數 1662 閱讀 7342

聰聰考試

難度級別:c; 執行時間限制:1000ms; 執行空間限制:262144kb; **長度限制:2000000b

試題描述

聰聰是乙個善良可愛、睿智聰慧的好孩子。聰聰是100%的學霸,這一天她在考數學。聰聰很快做到了最後一道題:「高一八班有n個人,從1到n編號,一次互判作業時,老師隨機將作業發到這n個人手中。已知有k個人拿到的不是自己的作業,那麼請問有多少種情況符合條件呢?」這麼簡單的問題聰聰當然會做了,她想考考你,你能不能比她先給出問題的答案呢?

輸入共1行,包含2個整數n和k。

輸出共1行,包含1個整數,表示答案。由於答案可能很大,請輸出答案模10007的餘數。

輸入示例

4 3輸出示例

8其他說明

對於30%的資料,0≤k≤n≤10。

另有10%的資料,k=0。

另有10%的資料,k=1。

對於70%的資料,0≤k≤n≤10000。

對於100%的資料,0≤k≤1000000,1≤n≤1000000000。

題解:n個人當中有k個人拿到的一定不是自己的作業,我們只需要考慮k個人沒有拿到自己作業的情況,所以我們可以先來乙個dp陣列儲存到k的全錯排列。動規方程是:dp[i]=(i-1)*dp[i-1]+(i-1)*dp[i-2](dp[i]代表i個人,全部拿到的不是自己作業的種類數)。

有一種情況是:假如當前有i個人,我們可以假設前i-1個人拿到的全都不是自己的作業,那麼第i個人拿到的一定是自己的作業,所以我們可以讓第i個人的作業與前i-1任意乙個人的作業進行交換,就是(i-1)dp[i-1]。

還有一種情況:就是假設前i-1個人中有1個人拿到自己的作業,也就是說第i個人一定要與拿到自己的作業的人的作業進行交換,這樣算出來就是(i-1)dp[i-2]。

以上兩種情況構成了所有的情況,所以我們可以得到dp方程:dp[i]=(i-1)*dp[i-1]+(i-1)*dp[i-2]

我們需要從n個人中選取k個人拿到的不是自己的作業,對於每一次選取,都有dp[k]種情況,所以最後答案是dp[k]*c(n,k)。

但是由於資料比較大,在處理c(n,k)的時候應該用盧卡斯定理。

以下是**:

1 #include2

#define maxn 1000000+10

3using

namespace

std;

4const

int mod=10007;5

int qp_mod(int x,int

n)12

return

b;13}14

int comb(int n,int

m)22 m=qp_mod(m,mod-2

);23

for(int i=n;i>=n-m+1;i--)

27return

m;28}29

int lucas(int n,int

m)35

return

ans;36}

37int

n,k;

38int

dp[maxn];

39int

main()

45 dp[1]=0;dp[2]=1;46

for(int i=3;i<=k;i++)

49 cout

50 }

view code

組合數取模

複習了一下組合數取模,當然推薦檢視acdreamer的部落格啦,寫的確實好啦,自己把裡面的題目全a掉了。include include include include include include include using namespace std typedef long long ll l...

組合數取模

對於c n,m mod p。這裡的n,m,p p為素數 都很大的情況。就不能再用c n,m c n 1,m c n 1,m 1 的公式遞推了。這裡用到lusac定理 for non negative integers m and n and a prime p,the following congr...

組合數取模

組合數c m,n 表示在m個不同的元素中取出n個元素 不要求有序 產生的方案數。定義式 c m,n m n m n 並不會使用latex qaq 根據題目中對組合數的需要,有不同的計算方法。運用乙個數學上的組合恒等式 oi中稱之為楊輝三角 c m,n c m 1,n 1 c m 1,n 證明 1.直...