POJ 2244:Eeny Meeny Moo(稍加变形的约瑟夫问题)
Description
你肯定经历过太多太多的人同时上网吧?网络会变得非常,非常慢。
为了解决这个问题,Ulm大学建立了一种机制:在高峰时段公平地断开某些城市的网络。德国的城市被随机地编号为1到n。Freiburg编号为1,Ulm编号为2,Karlsruhe编号为3,其他的也是完全随机的编号。
然后数字m会被随机的选取,网络总是会先断开城市1的网络,然后每m个城市断开一个城市,并且从1到n不断循环,且忽略那些已经被断网的城市。比如,如果n=17,m=5,则网络断开的城市顺序为[1,6,11,16,5,12,2,9,17,10,4,15,14,3,8,13,7]。并且还要规定Ulm城市会被最后一个断开网络,因此给定n,我们需要小心的选取m,确保城市2会被最后一个断开。
你的工作是写一个程序,读取城市数量n,需要确定最小的整数m,使得Ulm城市的网络会被最后一个断开。
Input
输入将包含一行或多行,每行包含一个正整数n($3\le n<150$),表示城市的数量,如果输入0,则停止。
Output
对于每行输入,都会打印一个正整数m满足题目的要求。
Sample Input
3 4 5 6 7 8 9 10 11 12 0
Sample Output
2 5 2 4 3 11 2 3 8 16
分析
此题题目的意思是对德国城市编号,编号如下:
1 2 3 4 .... n
因为1总是第一个被选择,因此其实就是对2到n的城市进行约瑟夫,且保证2为最后的幸存者,因此我们可以对他们再次编号:
原来:1 2 3 4 .... n
现在: 1 2 3 .... n-1
题目转变为了n-1个人,且幸存者编号为1的约瑟夫问题。
代码
1 import java.util.Scanner; 2 3 public class Main { 4 public static int josephus1(int n,int k){ 5 int r = 1; 6 for(int i=2;i<=n;i++){ 7 r = (r + k - 1) % i + 1; 8 } 9 return r; 10 } 11 public static void main(String[] args) { 12 Scanner in = new Scanner(System.in); 13 int n = 0; 14 while((n=in.nextInt())!=0){ 15 if(n==0) return; 16 int i = 2; 17 while(true){ 18 int pos = josephus1(n-1, i); 19 if(pos==1){ 20 System.out.println(i);break; 21 } 22 i++; 23 } 24 } 25 } 26 }