您的位置:首页 > 其它

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

2013-08-04 11:34 281 查看
这道题目悲剧了,约瑟夫环的数学解决办法,这从来没听过呀。

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

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

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

有个公式: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
+ 1) % n;
if (ans <= 0)
{
ans += n;
}
printf("%d\n", ans);
}
// system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: