HDU4841 圓桌問題

2022-07-09 03:06:10 字數 1170 閱讀 3789

如果真的按照題目中給定 \(n\) 的範圍,暴力模擬做法是不可行的,

然而貌似資料範圍沒有那麼大,所以可以逐圈模擬標記壞人;

另外,對於經典的約瑟夫問題,只需求出最後活下來的人的編號,

是可以用遞迴的方法 \(o(n)\) 解決的;

我們假設 \(f(n, m)\) 表示 \(n\) 個人依次報數報出 \(m\) 則被殺死時,

最終活下來的人的編號,為方便討論,從 \(0\) 開始編號,

先不妨假設 \(m <= n\),則第一輪報數,\(m - 1\) 被殺死,

\(m\) 可看成問題規模為 \(n - 1\) 時,編號為 \(0\) 的人,

那麼在問題規模為 \(n\) 時最終活下來的人編號為 \(m + f(n - 1, m)\),

此外還需取模保證答案在 \([0, n)\);

如果 \(m > n\),那麼第乙個被殺死的人編號為 \(m \% n - 1\),

於是答案為 \(m \% n + f(n - 1, m)\),

整理後可知,\(f(n, m) = (m + f(n - 1, m)) \% n\);

而當 \(n = 2\) 時,若 \(m\) 為偶數則答案為 \(0\),若 \(m\) 為奇數則答案為 \(1\)。

實際上,如果規定 \(n = 1\) 時,答案為 \(0\)(初始狀態就剩下 \(0\) 乙個人),

也能根據上述遞迴公式推出 \(n = 2\) 時的答案。

上述解法依然可以繼續優化,

如果 \(m + f(n - 1, m)\) 不超過 \(n\),則不必取模,

那麼我們其實可以通過遞推的做法,每次從 \(1\) 到 \(n\) 列舉問題規模,

如果不需要取模,則不必依次列舉,而是可以跳躍著增長問題規模,

具體來說,答案每次增加 \(m\),而問題規模每次增加 \(1\),

二者差距每次縮小 \(m - 1\),則可計算得出每次能直接增加的問題規模大小。

點選展開

#include #include using namespace std;

vectorperson;

int main()

for (int i = 0, j = 0; i < 2 * n; ++i)

puts("\n");

}return 0;

}

HDU 4841 圓桌問題

acm模版 這個題簡單的來就是暴力列舉約瑟夫環,當然,太暴力也不好,適當的用資料結構優化一下也是有必要的,這裡用向量維護,成功水過。include include include include include using namespace std const int maxn 4e4 const...

hdu4841 圓桌問題

圓桌上圍坐著2n個人。其中n個人是好人,另外n個人是壞人。如果從第乙個人開始數數,數到第m個人,則立即處死該人 然後從被處死的人之後開始數數,再將數到的第m個人處死 依此方法不斷處死圍坐在圓桌上的人。試問預先應如何安排這些好人與壞人的座位,能使得在處死n個人之後,圓桌上圍坐的剩餘的n個人全是好人。多...

HDU 4841 圓桌問題

圓桌上圍坐著2n個人。其中n個人是好人,另外n個人是壞人。如果從第乙個人開始數數,數到第m個人,則立即處死該人 然後從被處死的人之後開始數數,再將數到的第m個人處死 依此方法不斷處死圍坐在圓桌上的人。試問預先應如何安排這些好人與壞人的座位,能使得在處死n個人之後,圓桌上圍坐的剩餘的n個人全是好人。i...