《算法竞赛-训练指南》第一章-1.26_LA 3882

来源:互联网 发布:非法经营期货软件投诉 编辑:程序博客网 时间:2024/06/16 17:52

这道题目悲剧了,约瑟夫环的数学解决办法,这从来没听过呀。


上网查,有了点眉目,也确实是这么回事,思想是这个样子的,因为你每次报数都会去掉一个人,咱如果不考虑编号,就拿人(人都是不同的。)来说,只要你定好了开头,那么肯定是唯一的那个人是最后一个留下来的,开头不变,那个唯一的人也是不会变的。


其实咱们现实生活中玩这个游戏也是按照:去掉一个人,重新排号,然后去掉一个人,再重新排号,再去掉一个人,然后得出最后一个人。

这其实是符合我们常识的,但是咱们解决问题可就麻烦了点,就是我们怎么区别这些人呢,当然是要给每个人编上一个唯一的编号咯,那咱们需要解决的唯一问题就是怎么样得到,我们开始设定好的编号,而不是我们每次重新编写的编号呢?

有个公式:f[i] = (f[i - 1] + M) % i;说不好理解也是有点不好理解,但是如果理解起来是还能理解,其实就是你做i的时候肯定已经去掉了那个M-1的编号,那其实你用f[i-1]得到的重新编号加上咱们的M就是那个就是开始设定的编号。


但是不能多想,多想可能就把你的脑子给撕扯了。还得整,我非得整明白不行!

最终的结果我也想的不是很明白,一会吃饭回来继续想,想好继续编辑。

贴出代码:

#include <stdio.h>#include <string.h>#include <iostream>#include <string>using namespace std;const int MAXN = 10000 + 5;int f[MAXN];int main(){int n, k, m;while (scanf("%d%d%d", &n, &k, &m) != EOF){if (n == 0 && k == 0 && m == 0){break;}if (n == 1){printf("1\n");continue;}f[1] = 0;for (int i = 2; i <= n; i++){f[i] = (f[i - 1] + k) % i;}int ans = (m - k + f[n] + 1) % n;if (ans <= 0){ans += n;}printf("%d\n", ans);}//system("pause");return 0;}


原创粉丝点击