cqyz 遞迴 p3531 約瑟夫問題 6

2021-08-08 16:14:31 字數 2029 閱讀 9907

【問題描述】

yjc 很喜歡玩遊戲,今天他決定和朋友們玩約瑟夫遊戲。

約瑟夫遊戲的規則是這樣的:n個人圍成一圈,從1 號開始依次報數,當報到m 時,報1、2、…、m-1 的人出局,下乙個人接著從1 開始報,保證(n-1)是(m-1)的倍數。最後剩的乙個人獲勝。

yjc 很想贏得遊戲,但他太笨了,他想讓你幫他算出自己應該站在哪個位置上。

【輸入格式】

第一行包含兩個整數n 和m,表示人數與數出的人數。

【輸出格式】

輸出一行,包含乙個整數,表示站在幾號位置上能獲得勝利。

【輸入樣例】

10 10

【輸出樣例】

10【資料範圍】

對於30%的資料,2 ≤ n ≤ 1000。

對於70%的資料,2 ≤ n ≤ 1000000。

對於100%的資料,2 ≤ m ≤ n ≤ 2^63-1

【**】

八中供題

【原題傳送矩陣】

p3531 約瑟夫問題

【思路梳理】

「看待乙個問題不能仰視之,要居高臨下地審視之。」——mr. he

這句話是我校競賽教練 mr.he的原話,意指對於任何乙個題不應該只想著模擬,而應該結合自己的所學知識,跳出思維的怪圈,真正做乙個acmer。

這句話用於詮釋此題不能再恰當了。拿到問題的第一瞬間,不才我是一頭霧水。事後才在高人的指點下琢磨出了100分演算法。

看資料規模,30分模擬,70分似乎應該是考慮貪心或者動態規劃,而100分則達到了2^61 -1,不可能通過儲存實現,應該是使用遞迴呼叫,將結果作為引數或者返回值傳遞後輸出。

演算法1:30分模擬

按照題目描述地模擬,將報1~m-1的人標記掉,直到只剩1個人,輸出之。

演算法2: 70分遞推

這一下就有意思了。知道是遞推,不難想到設定狀態函式f[i]=在前i個人中進行約瑟夫遊戲剩下的人的編號。但是轉移呢?在每m個人中,報1~m-1的人都會出局,而只剩下了第m個人。所以每增加m-1個人,答案往後移m位。所以遞推式:f[i]=f[i-m+1]%(i-m+1)+m,邊界f[1]=1.時間複雜度這裡寫描述。

演算法3:100分遞迴

推公式找規律。問什麼設什麼,設定乙個函式solve(x),表示在這x個人中進行約瑟夫遊戲時最後乙個人的編號。下面思考遞迴。

當前有x個人的話,那麼這x個人可以分成兩部分:

前面的乙個部分可以被均分為了a組,每一組都有m個數;後面的乙個part有任意個,但是小於m。前面的part1裡面的人數顯然是m的a倍,那麼未出局的就是編號為m的整數倍的人;後面的part2是不足再報m個數的人,總共數量是n%m。

我們繼續對這些剩下的人重新編號(因為還有人沒有報數,所以新的編號要從當前編號為am+1的人開始),將後面的n%m個人拉到新隊伍的前面來。而前面總共是n/m組,那麼此時還未出局的總人數為part1的n/m個人和part2的n%m個人。我們繼續在這些人裡重新進行約瑟夫遊戲。

什麼時候停止呢?顯然最後肯定會有乙個人留下來(n-1是m-1的整數倍),所以邊界是solve(1)=1。

此時遞迴已經開始回溯,返回值是這一輪進行以後留下來的人的標號。我們要求出他在上一輪進行後留下來的編號,只需要找到他的位置即可。當前來說,因為後面的人數都小於m,那麼也就是說這些人會全部出局(留下來的人在part1),而且一定是m的整數倍(非整數倍都出局了)。設返回值為y,則我們可以知道他的編號為:(y-n%m)*m。

#include

#include

#define maxn 1000005

using

namespace

std;

long

long n,m;

long

long f[maxn];

void solve30()

}printf("%d",last);

}void solve70()

int main()

約瑟夫環問題 遞迴推導

題目描述 n個數,編號為 0 1,n 1 排成乙個圓圈,從數字 0 開始,每次從這個圓圈中刪除第 m 個數,請問最後乙個剩下的數是多少?推導過程 定義乙個函式f n,m 為 n 個數中取 m 最後剩下的編號。第乙個被刪除的數是 m 1 n,記為 k 此時因為序列已經不連續,函式可以定義為f n 1,...

遞迴題目練習 約瑟夫問題

參考鏈結 題目描述 約瑟夫問題是乙個非常著名的趣題,即由n個人坐成一圈,按順時針由1開始給他們編號。然後由第乙個人開始報數,數到m的人出局。現在需要求的是最後乙個出局的人的編號。給定兩個int n和m,代表遊戲的人數。請返回最後乙個出局的人的編號。保證n和m小於等於1000。測試樣例 5 3返回 4...

P1996 約瑟夫問題

題目描述 nnn 個人圍成一圈,從第乙個人開始報數,數到 mmm 的人出列,再由下乙個人重新從 111 開始報數,數到 mmm 的人再出圈,依次類推,直到所有的人都出圈,請輸出依次出圈人的編號。輸入格式 輸入兩個整數 n,mn,m n,m。輸出格式 輸出一行 nnn 個整數,按順序輸出每個出圈人的編...