问题描述:n 个数字(0,1,…,n-1)形成一个圆圈,从数字0 开始, 每次从这个圆圈中删除第K 个数字(第一个为当前数字本身,第二个为当前数字的下一个
数字)。
当一个数字删除后,从被删除数字的下一个继续删除第K 个数字。
求出在这个圆圈中剩下的最后一个数字m
术语定义:n是最开始的数字总数,m是圆圈中的最后一个数字,p(i)第i次删除数字之后,还剩余的数字个数,p(1)=n-1,p(n-1)=1,0=<i<=n-1;
我们可以对p(i)进行编号,0....p(i)-1,下标为0开始的地方就是第i次被删除的数字的下一个数字开始。
例如n=5,k=3,i=0;时p(0)=5
编号:0 1 2 3 4
数值:0 1 2 3 4
i=1时p(1)=4
编号:0 1 2 3
数值:3 4 0 1
i=2时p(2)=3
编号:0 1 2
数值:1 3 4
i=3时p(3)=2
编号:0 1
数值:1 3
i=4时p(4)=1
编号:0
数值:3
思路:对于这种问题最好先模拟几次,寻找规律。要么是自顶向下N个数字每次减少一个数字,直到最后一个数字;要么是从最后一个数字开始,慢慢恢复到最后一个数字m在N的位置。
采用自底向上的思路考虑,对于n=1,无论k是多少,m就是0;
假设n=2,那么p(0)=2,p(1)=1,最后一轮下标为0的数值,就是m,那么最后一轮的下标,对应上一轮的下标是多少?
示例:
n=2,k=3
p(0)=2
编号:0 1
数值:0 1
p(1)=2
编号:0
数值:1
可见对于对于最后一轮时,计算出m=1,它对应的编号为0,但是它对应的上一轮编号为1,找出编号的对应关系就可以找到最后一个数字m。
也就是说我们要求的对应关系是,经过i次删除数据之后,假设第i次删除数据的下标为j,那么j所指向的值,在第i-1的下标是多少?
第i次删除数据时,指向的下标为K%P(i-1),第i次下标为0的值value,与该value在p(i-1)的关系是什么?p(i-1)中的第(K+1)%(n-1)对应的就是第i次
的0。
由此我们可以从p(n-1)次下标为0的位置推出对应的p(n-2)对应的位置依次类推,就可以推出m在p(0)中的相应位置。
附上代码。
package nAndK; import java.util.Scanner; public class NAndK { private static Scanner myscanner; public static void loopset() { myscanner=new Scanner(System.in); boolean goon=true; while(goon) { System.out.println("请输入n和k"); System.out.print("n="); int n=myscanner.nextInt(); System.out.print("k="); int k=myscanner.nextInt(); int m=0; for(int i=2;i<=n;i++) { m=(m+k)%i; } System.out.println("("+n+","+k+","+m+")"); } } public static void main(String[] args) { loopset(); } }
PS:假设:不是n 个数字(0,1,…,n-1)形成一个圆圈,是从(1,2,...,n)围成一个圈时,模运算的方便,可以仍然按照(0,1,…,n-1)开始计算,
最后返回M+1即可。
菜包子
2013年5月15日19:15:23
于马甸桥东