聰聰考試
難度級別: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 #include2view code#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 }
組合數取模
複習了一下組合數取模,當然推薦檢視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.直...