File tree Expand file tree Collapse file tree 1 file changed +27
-0
lines changed
Expand file tree Collapse file tree 1 file changed +27
-0
lines changed Original file line number Diff line number Diff line change 1+ ข้อนี้ต้องถามว่าหากต้องแบ่งหุงข้าว $N$ จาน โดยแต่ละครั้งหุงได้เกิน $K$ จานต่อครั้ง จะสามารถแบ่งหุงจนครบ $N$ ได้กี่วิธี
2+
3+ สำหรับข้อนี้วิธีแรกที่เห็นได้ง่ายที่สุดคือ Dynamic Programming โดยเห็นได้ว่า $dp[ i] = \Sigma_ {j=\max(0,i-k)}^i dp[ j] $ (ในการหุงครั้งจากต้องการ $i$ จะเหลือต้องการ $j$ จานโดย $i-k\leq j\leq i-1$)
4+
5+ แต่เนื่องจากข้อนี้กำหนด $N \leq 100000, K \leq 100000$ วิธีนี้ที่ใช้เวลา $\mathcal{O}(NK)$ จึงช้าเกินไป เราจึงต้องใช้วิธีที่เร็วกว่านี้
6+
7+ เราสามารถกำหนด $C[ i] = \Sigma_ {j=0}^i dp[ j] $ ซึ่งจะทำให้สามารถคำนวณ $dp[ i] = C[ i-1] $ เมื่อ $i-k-1 < 0$ และ $dp[ i] = C[ i-1] - C[ i-k-1] $ เมื่อ $i-k-1 \geq 0$ ในเวลา $\mathcal{O}(1)$ ($C[ i] $ สามารถคำนวณเป็น $C[ i] =C[ i-1] + dp[ i] $ ในเวลา $\mathcal{O}(1)$ เช่นกัน)
8+
9+ ดังนั้นจึงต้องใช้เวลาเพียง $\mathcal{O}(1)$ สำหรับการคำนวณ $C[ i] $ และ $dp[ i] $ สำหรับแต่ละ $i \leq N$ ทั้งหมดจึงใช้เวลา $\mathcal{O}(N)$
10+
11+ โค้ดประกอบคำอธิบาย
12+
13+ ``` cpp
14+ dp[0 ] = 1 ;
15+ C[0 ] = 1 ;
16+ for (int i=1 ;i<=n;i++)
17+ {
18+ if (i-k-1>=0)
19+ dp[i] = C[i-1] - C[i-k-1];
20+ else
21+ dp[i] = C[i-1];
22+ dp[i] = dp[i] %2009;
23+ if(dp[i]<0)
24+ dp[i]+=2009;
25+ C[i] = C[i-1] + dp[i] %2009;
26+ }
27+ ```
You can’t perform that action at this time.
0 commit comments