2018瀋陽k(經典的約瑟夫環)

2021-09-01 04:40:44 字數 1878 閱讀 5299

位址

首先,對於經典的約瑟夫環問題,我們記f(n

,m

)f(n,m)

f(n,m)

表示初始有n

nn個人,第m

mm個出隊的人是誰(從0號開始報數)。則有遞推式f(n

,m)=

(f(n

−1,m

−1)+

k)%n

f(n,m)=(f(n-1,m-1)+k)\ \%\ n

f(n,m)

=(f(

n−1,

m−1)

+k)%

n 其中k

kk表示每報數k

kk次乙個人出隊,注意編號從0開始

遞推式的證明:考慮現在有n

nn個人圍成一圈,然後從0開始報數。假設第乙個出隊的人是x

xx ,這時還有n−1

n-1n−

1個人,我們從剛剛出去的那個人的下乙個人從0重新編號,那麼以當前局面重新開始,第m−1

m-1m−

1個出隊的人是初始所求的同乙個人,但編號不同,差多少呢?即f(n

,m)=

(f(n

−1,m

−1)+

k)%n

f(n,m)=(f(n-1,m-1)+k)\ \%\ n

f(n,m)

=(f(

n−1,

m−1)

+k)%

n 。 +1 -1 細節手玩一下。

回到本題,由於m,k

m,km,

k可能會很大,但不會同時很大,當m

mm較小的時候(m

<=k

m<=k

m<=k

),直接遞推即可。

下面考慮m

>

km>k

m>

k的情況,會發現模數大部分情況下遠大於k

kk,也就是說可以用乘法代替多次加法,這樣可以降低時間複雜度。具體代替多少次呢?考慮f(a

,b)=

an

sf(a,b)=ans

f(a,b)

=ans

, 假設代替x

xx次,則f(a

+x,b

+x)=

ans+

x∗

kf(a+x,b+x) = ans+x*k

f(a+x,

b+x)

=ans

+x∗k

進行取模的等價條件是ans

+x∗k

>=a

+x

ans+x*k > =a+x

ans+x∗

k>=a

+x,即x

>=a

−ans

k−

1x>=\frac

x>=k

−1a−

ans​

即代替次數確定了(整除不整除,快加到m

mm了等細節注意一下即可)。

時間複雜度o(感

覺能過)

o(感覺能過)

o(感覺能過

)

#include

using namespace std;

typedef

long

long ll;

const

int maxn=

2e6+10;

ll m,n,k;

ll f[maxn]

;int

main()

else

else

} cout<1<}return0;

}

2018瀋陽現場賽K題題解 約瑟夫問題

題目大意 給定初始人數n,步長m,求第k個被彈出的人的編號。這題有乙個非常重要的條件,那就是sum min m,k 2e6 因此我們可以分情況討論。下面假設編號從0開始。k m 此時k最大為2e6。因此我們可以使用乙個o k 的方法求出答案。設f n,k 為初始為n個人時第k個被彈出的人。第乙個被彈...

2018瀋陽模擬賽 K

這道題很費勁的將所有superme number找了出來,發現317以後就再也沒有該數了 1,2,3,5,7,11,13,17,23,31,37,53,71,73,113,131,137,173,311,317 這個過程過了 很久沒寫字串的題,字串的知識又糊了。輸入一串很長的數,可以用乙個char型...

經典約瑟夫環問題

1 coding utf 8 2 author diva 3 使用者輸入n,n代表人數,圍成一圈,順序排號 4 從第乙個開始報數,1,2,3,數到3的人,退出圈子 5 6 報數邏輯,數到3的把對應的位置置為0,直到剩下最後乙個人 7 def num report list create 8 n 0 ...