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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

北航算法作业一 约瑟夫环问题

發布時間:2025/4/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 北航算法作业一 约瑟夫环问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.單向鏈表模擬

class Node:def __init__(self, num, next):self.num = numself.next = nexta = [] # n個人 n = 3 # 數到k的人死去 k = 2 for i in range(0, n):a.append(Node(i, (i + 1) % n)) # 計數器 counter = 1 # 現在的人 now = a[0] while True:next = a[now.next]if next == now:#就剩下一個人了,游戲結束breakelse:counter += 1if counter == k:#計數器為k,要死人了counter = 0now.next = next.nextprint(str(next.num)+" has died",end='\n')else:#不死人,now=next,向后走一格now=next #打印唯一的幸存者 print(now.num)

二.遞推公式法

f(n)=[f(n-1)+k]%n

編號從0開始,f(n)表示n個人數到k的死去最后的幸存者,顯而易見第一個死去的人是(k-1)%n,死者后面一人編號為0,再后面為1,以此類推,構成一個新的f(n-1).所以f(n)中的幸存者就是f(n)=[f(n-1)+k]%n.

#n個人 n=100 a=[0]*n #數到k的人死去 k=2 a[1]=0 for i in range(1,len(a)):a[i]=(a[i-1]+k)%i for i in range(1,len(a)):print(a[i],end=' ')

輸出為

0 0 2 0 2 4 6 0 2 4 6 8 10 12 14 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70

很顯然可以找到規律,數字周期為第0個周期長度為1,第1個周期長度為2,第2個周期長度為4,第三個周期長度為8....對于數字n,它所在的周期為log2(n),數字n在周期中的列數為n-2^log2(n).

當k=2時,f(n)=[n-2^log2(n)]*2

驗證上述結論:

from math import * for i in range(1,100):print((i-2**int(log2(i)))<<1)

在上述表述中,一切計數都從0開始.從0開始,你會發現問題的表達形式會簡單很多,從0開始計數確實應該成為一種習慣.

三.k=2時的另一種遞推公式

f(2n)=2*f(n)

f(2n+1)=f(n)+1

下標一律從0開始,當有2n個人,數完一圈之后,奇數號人全跪了.給剩下的人重新編號,原來的0號還是0號,原來的2號變成1號,原來4號變成2號....即原來的2n號變成了現在的n號.剩下n個人的幸存者為第f(n)號,這個人對應原來的f(n)*2號.所以f(2n)=2f(n).

當有2n+1個人,數完一圈之后,奇數號人全跪了,最后一個人2n號沒有跪,下一個跪的是0號.這樣第一圈算跪了n+1個人.對剩下的n個人重新編號,原來的2號變成0號,原來的4號變成1號,原來的6號變成2號,原來的8號變成3號....即原來的2n號變成了現在的n-1號.剩下n個人的幸存者為f(n)號,對應原來的(f(n)+1)*2號,所以f(2n+1)=2f(n)+2.

對于這種問題,關鍵在于重新編號.

四.比較快的遞推公式法

遞推公式f(n)=(f(n-1)+k)%n,復雜度為O(n).有一個更快的遞推式:

f(n)=[f(n-n/k)+n-n%k+f(n-n/k)/(k-1)]%n

f(n-n/k)第一輪輸完之后,n/k個人死了,就剩下n-n/k個人.剩下的任務就是找到f(n-n/k)這個人對應f(n)中的哪個人.f(n-n/k)每(k-1)個人中可以插入一個死者,這些死者是要算數的.最后一個死者是n-n%k,他的下一個為0號,這是偏移量.這個遞推公式復雜度

f(n)=常數*f(n-n/k)

復雜度為log(n)級別.

五.關于約瑟夫環

約瑟夫環花樣繁多,比如給定一個數組

1 4 當第一個人死去,下一個死去的人是第一個人左邊的第4個人

2 3 當2號人死去,下一個死去的人是第二個人左邊第3個人

3 4 當3號人死去,下一個死的人是他左邊的第4個人

...

給定一個數組,問最后的幸存者是誰.

這個問題可以用線段樹來求解.

總結

以上是生活随笔為你收集整理的北航算法作业一 约瑟夫环问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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