题目链接
约瑟夫环问题
假设有n n n 个数,编号为0 , 1 , 2 , ⋯ n − 1 0,1,2,\cdots n-1 0 , 1 , 2 , ⋯ n − 1 ,其中0和n − 1 n-1 n − 1 相连,形成一个环,如图:
从0开始数k k k 个,将这个数从环中移除,再数k k k 个,再移除,问最后一个数是多少。
假设n = 7 , k = 3 n=7,k=3 n = 7 , k = 3 。那么第一次删除2,数列变成:
0
1
2
3
4
5
6
0
1
3
4
5
6
此时,1和3分离开了,为了使1和3连续,我们可以将列表重新编号,从被删除的下一个数开始编号,即:
\
0
1
2
3
4
5
6
编号前
0
1
3
4
5
6
编号后
4
5
0
1
2
3
这样新表的下一个要删除的数编号为2,而旧表中为5。
不难发现,新旧表的下一个待删除的数的编号存在这样一个关系:
D e l e t e d N o d e 新 表 = ( D e l e t e d N o d e 旧 表 − k ) m o d 旧 表 中 剩 余 的 数 的 个 数 DeletedNode_{新表}=(DeletedNode_{旧表}-k)\bmod 旧表中剩余的数的个数 D e l e t e d N o d e 新 表 = ( D e l e t e d N o d e 旧 表 − k ) m o d 旧 表 中 剩 余 的 数 的 个 数
根据模数的性质,可以推出:
D e l e t e d N o d e 旧 表 = ( D e l e t e d N o d e 新 表 + k ) m o d 旧 表 中 剩 余 的 数 的 个 数 DeletedNode_{旧表}=(DeletedNode_{新表}+k)\bmod 旧表中剩余的数的个数 D e l e t e d N o d e 旧 表 = ( D e l e t e d N o d e 新 表 + k ) m o d 旧 表 中 剩 余 的 数 的 个 数
那么由6个数删到一个数的数列变化:
n
\
0
1
2
3
4
5
6
7
-
0
1
2
3 \color{red}{3} 3
4
5
6
6
编号前
0
1
3
4
5
6
6
编号后
4
5
0
1
2
3
5
编号前
4
5
0
1
3
5
编号后
1
2
3
4
0
4
编号前
1
3
4
0
4
编号后
3
0
1
2
3
编号前
3
0
1
3
编号后
0
1
2
2
编号前
0
1
2
编号后
0
1
1
编号前
1
1
编号后
0
记S i S_i S i 为n = i n=i n = i 时的编号后的数列,F ( S i ) F(S_i) F ( S i ) 为最后被删除的数在S i S_i S i 中的编号,则:
F ( S i ) = ( F ( S i − 1 ) + k ) m o d ∣ S i ∣ F(S_i)=(F(S_{i-1})+k)\bmod |S_i| F ( S i ) = ( F ( S i − 1 ) + k ) m o d ∣ S i ∣
并且有:F ( S 1 ) = 0 F(S_1)=0 F ( S 1 ) = 0
那么有:
F ( S 2 ) = ( F ( S 1 ) + 3 ) m o d 2 = 1 F ( S 3 ) = ( F ( S 2 ) + 3 ) m o d 3 = 1 F ( S 4 ) = ( F ( S 3 ) + 3 ) m o d 4 = 0 F ( S 5 ) = ( F ( S 4 ) + 3 ) m o d 5 = 3 F ( S 6 ) = ( F ( S 5 ) + 3 ) m o d 6 = 0 F ( S 7 ) = ( F ( S 6 ) + 3 ) m o d 7 = 3
F(S_2)=(F(S_1)+3)\bmod 2=1\\
F(S_3)=(F(S_2)+3)\bmod 3=1\\
F(S_4)=(F(S_3)+3)\bmod 4=0\\
F(S_5)=(F(S_4)+3)\bmod 5=3\\
F(S_6)=(F(S_5)+3)\bmod 6=0\\
F(S_7)=(F(S_6)+3)\bmod 7=3\\
F ( S 2 ) = ( F ( S 1 ) + 3 ) m o d 2 = 1 F ( S 3 ) = ( F ( S 2 ) + 3 ) m o d 3 = 1 F ( S 4 ) = ( F ( S 3 ) + 3 ) m o d 4 = 0 F ( S 5 ) = ( F ( S 4 ) + 3 ) m o d 5 = 3 F ( S 6 ) = ( F ( S 5 ) + 3 ) m o d 6 = 0 F ( S 7 ) = ( F ( S 6 ) + 3 ) m o d 7 = 3
求出了结果为3,与表格中的一致。
回归题目
而题目中是从m开始,而非从第一个开始。因为从第k − 1 k-1 k − 1 个开始移除,那么接下来会从0开始编号,那么从m − 1 m-1 m − 1 开始的话接下来会从m − k m-k m − k 开始编号,并且题目从1开始编号,因此答案还要加上m − k + 1 m-k+1 m − k + 1 。有因为 答案+ m − k + 1 +m-k+1 + m − k + 1 有可能小于等于0,因此再判断一下即可。
#include <iostream>
using namespace std;
int main ( ) {
int n, k, m;
while ( true ) {
cin >> n >> k >> m;
if ( ! n && ! k && ! m) {
break ;
}
int ans = 0 ;
for ( int i = 2 ; i <= n; ++ i) {
ans = ( ans + k) % i;
}
ans = ( m - k + 1 + ans) % n;
if ( ans <= 0 ) {
ans + = n;
}
cout << ans << endl;
}
}