日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

约瑟夫环(丢手绢问题)

發布時間:2023/12/13 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 约瑟夫环(丢手绢问题) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 問題描述
  • 思路
  • 代碼實現


問題描述

有 1~N 個數字,從 1~m 依次報數,數到 m 的數字要被刪掉,求最后剩下的數字是?


思路

第一次報數第二次報數
1n-m+1
2n-m+2
m-2n-2
m-1n-1
m被刪掉了
m+11
m+22
n-1n-1-m
nn-m

通過上面的表格,我們可以發現這樣的規律:

將某數字第一次報數設為 first ,第二次報數設為 second 。那么存在這樣的關系:first=(second+m?1)%n+1first = (second + m - 1) \% n + 1first=(second+m?1)%n+1(公式一)

為什么不是 first=(second+m)%nfirst = (second + m) \% nfirst=(second+m)%n (公式二)呢?其實一開始我確實總結出來的是公式二,但是發現有個漏洞,數字編號是從 1 開始的,而公式二的編號是從 0 開始的,具體來說,就是當 second = n-m 時,first = 0 。可以看到并不符合實際,first=n 才對。換言之,也就是如果我們從 0 開始計數,那么公式二是可用的,如何從 0 開始計數呢? 答案就是把數字序列存到數組里嘛~

因此,將公式二可以進化為 first=(second+m)%n+1first = (second + m) \% n + 1first=(second+m)%n+1(公式三),但是簡單的為公式二的結果 +1 ,就導致在公式二中,本來只有 second = n-m 結果不符合實際,而在公式三中,變成了只有 second = n-m 的結果符合實際,原本沒問題的都變得有問題了……這是因為我們沒有做到加減均衡,只有 +1,而沒有 -1 。因此公式一應運而生~

那么我們可以得到這樣的規律:

當n>1時,f(n)=(f(n?1)+m?1)%n+1當 n>1 時,f(n) = (f(n-1) + m - 1) \% n + 1n>1f(n)=(f(n?1)+m?1)%n+1
當n=1時,f(1)=1當 n=1 時,f(1) = 1n=1f(1)=1

解釋一下就是,剩最后一個數的時候直接返回最后一次報數為 1 的數,反之則需要繼續刪除一個數。

而當 n-1=1 時,f(n) 也就意味著,最后一次報數為 1 的數,倒數第二次報數的時候它報的是幾。

那么對于 f(n-1) 的調用也就意味著,本次報數為 n 的數,下一次報數為幾。

說到這里已經很清楚了,顯而易見的遞歸思想。


代碼實現

int m; int yuesefu(int n){if(n == 1) return 1; // 最后一次報數為 1,開始回溯return (yuesefu(n-1) + m - 1) % n + 1; // f(n-1)==1的時候開始回溯,求最后一次報數為 1 的數,第一次報數為幾? }// 還可以再簡化 int m; int yuesefu(int n){return n == 1 ? 1 : (yuesefu(n-1) + m - 1) % n + 1; }// 如果將數字序列存入數組中,則可用公式二 int m; int yuesefu(int n){return n == 0 ? 0 : (yuesefu(n-1) + m) % n; }

總結

以上是生活随笔為你收集整理的约瑟夫环(丢手绢问题)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。