约瑟夫环问题:一圈共有N个人,从1开始报数,报到M的人OUT,然后重新开始报数,问最后OUT的人是谁?【N=10,M=3】
/* ①数组:遇到一次m count+1 直到count=n 结束 / 循环n-1次 不用count计算 / 从后往前推: 》j = 0 》for i 从 2 到 n: 》》j = (m+j)%i 》》最终第j个人会留下来(如果从1开始编号就是第j+1个人最终会留下来。 */ /* ②**递推思想:递推公式:可以用一个式子来表示数列{an}的第n项与它前一项或几项的关系 **找规律** 当有n个人时,变成一个子问题 (n-1)个人的报数问题,编号依次为0 1 2 3 ... n-1 ,求最后一轮的人在第一轮中的编号。【对于最后一轮来说,最后留下来的人正是最后一轮开始报数的人。我们只需要求出相邻的两轮之间,同一个人在后一轮的编号和在前一轮里的编号,那么就可以求出来这个人在倒数第二轮里的编号,求出倒数第二轮的对应编号,那么这个人对应在倒数第三轮的也能求出……直到对应到第一轮。】 例:n=5 m=5 每一轮编号都从开始报数的那个人开始算,那么第二轮出列的人在第二轮的编号是(m-1)%(n-1),在第一轮编号为[m + (m - 1) % (n-1)]%n。剩下各轮也是这样。 编号: 0 1 2 3 4 报数人:1 2 3 4 5 【5人 第一轮:报数为m的人编号为(m-1)%n,出列; 1 2 3 4 【4人 第二轮:有n - 1个人,编号为(m+0)%n的开始报数 2 3 4 【3人 2 4 【2人 4 【1人 so此轮编号为(m+i)%n的人将做为下一轮编号为i的人; 编号为F(n-1)的人肯定对应着上一轮的F(n) 所以有 F[n]=(F[n-1]+m)%n (n>1) 【F[1]=0 :剩最后一个人 此人编号为0】 **[补充知识]**求余、取模 区分 ex:4/3=1.3 求余 4/(-3)=1 商值向0方向舍弃小数位 4rem -3=1 取模 4/(-3)=2 商值向0方向舍弃小数位为 4mod -3=-2 唯一的区别在于: 当x和y的正负号一样的时候,两个函数结果是等同的;当x和y的符号不同时,rem函数结果的符号和x的一样,而mod和y一样。 */ #include<stdio.h> int main() { int n,m; while(scanf("%d %d",&n,&m)!=EOF) { int i,result=0; for(i=2;i<=n;i++) result=(result+m)%i; printf("%d\n",result+1); } return 0; } /* ③单向循环链表 */