有n個高度分別為1到n的人,從前到後站成一列,高的人會擋住矮的人。現在從前往後可以看到m個人,問一共有幾種站法?
輸入:一行兩個整數n,m∈【1,1000】,如題所述。
輸出:一行乙個整數,為答案mod 1e9+7的值。
時間限制:1s。空間限制:512mb。
樣例輸入①:3 2
輸出:3
解釋:一共有132、231、213,這三種方法可以從前往後只看到2人。
樣例輸入②:1000 500
輸出:761367694
解釋:答案很大,但是對1e9+7取過模。
錯誤思路:min值在最前面,則從後n-1人中隨機取m-1人,即組合數c(n-1,m-1);min值在第二個到最後,則從n人中隨機取m人,即組合數c(n,m)。
錯誤原因①:兩者相加顯然連第乙個樣例都過不了,然後還試圖湊式子c(n-1,m)+c(n-1,m-1)或者c(n-1,m-1)*(m-2)+c(n,m)之類的式子,都可以過樣例①,但是樣例②都不行。「隨機」這個思想本來就是錯的,隨機選的人中,只要中間有乙個比相鄰的矮,就看不見;然後花在組合數上的時間(盧卡斯,乘法逆元)就全浪費了。
正確思路:
①emmm…提示居然是對的,當然也是我排列組合太差了沒想到新的方法。按照第一類斯特林數的組合學解釋,p個不同人圍k個相同圓桌而坐,要求各桌非空,其不同方案數為第一類stirling數s(p,k)。結合題目的提示,每個人都可以擋住後面比ta矮的人,這樣一組就相當於乙個「圓桌」且各桌非空,所以符合第一類斯特林數的組合學定義。
②斯特林數的遞推式:s(p,k)=s(p-1,k-1)+(p-1)*s(p-1,k)。具體推導過程另外講。
③因為要一步步遞推,參考網上uva10128的題解(題目相似,只不過更難,還要從後往前看,可以看到k個人,再計算方案),然後使用dp(第一次寫dp,一臉懵逼)。
錯誤原因②:開了乙個dp[1005] [1005]的二維陣列,然後用memset置0,記憶體**、超時。
改進:用兩層for迴圈置0(或者在main函式外面定義二維陣列)。
錯誤**①:
#include#include#include#include#include#includeusing namespace std;
#define ll long long
const ll p=1e9+7;
ll inv(ll a)
ll c(ll n,ll m)
}dp[1][1]=1;
for(int i=2;i<=a;i++)//本來所有的i最大都是1005
}printf("%lld\n",dp[a][b]);
return 0;
}
第二週小測的題解
include using namespace std intmain cout include using namespace std intmain cout return0 結束 include include using namespace std const int m 20005 200...
2018 3 2周測總結
周測的內容是資料庫的內容。總的來說我這次測試不理想。我週末在家裡反思為什麼會這樣,我覺得我的態度沒有端正,大家都在同一起跑線,有好有壞說明大家不同的程度都有努力。這讓我確定了自己以後的學習計畫。再來說說題目,我在考前的確是複習了關鍵字和筆記,有些內容是在筆記上面沒有體現的,我也跟同學們確定了的確是沒...
第五周機測
快速排序模板 注意cmp按sort的寫 等號的時候一律交換 比如降序 return a b sort中是 return a b.pi return true else return false return false void mysort int left,int right,node a,bo...