关键是对删除后的剩余情况重新编号,再看新编号怎么映射回原先编号。

约瑟夫环问题

0 ~ i-1的i个数字排成环,每次数到m删一个数字,最后剩下哪个数?

第一次删除数字(m-1)%i,删除数字后开始重新编号0 ~ i-2,比如被删除数后面的数((m-1)+1)%i = m%i =重编号=> 0。反过来,0=映射回=> m%i,从删除后=映射回=>删除前 p(x)=(x+m)%i,i是删除前的个数。从最终只剩x=0逆推。

int ysf(int n, int m) {
	// 例如,(1+m) % len => 1,反过来就是 1 => (1+m) % len
	// 推广到 x => (x+m) % len
	int x = 0;  // 涉及到模运算,从0开始
	for (int i = 2; i <= n; i++) {
		x = (x + m) % i;
	}
	return x + 1;  // 从1开始编号
}