首页 > 代码库 > UVa 1394 约瑟夫问题的变形

UVa 1394 约瑟夫问题的变形

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4140

本来是要昨天来写这学习代码的,然后昨晚寝室又断电了,忍不住在这里吐槽一下,嗯,寝室天天断电。

题意就是输入n,k,m三个数,n个数排成一个圈,第一次删除m,以后每数k个数删除一次,求最后一个被删除的数。

言归正传,以前写过一个链表的约瑟夫问题,但是在这里肯定是会超时的。后来看了些参考,终于明白了怎么做。

把n个数从0数组开始存入,第一次删除第m个数后,也就是数组下标为m-1的数被删去,此时把数组下标为m的数重新作为0号位置,重新组成一个环,那么此时下标为m的数的下标变为了0。

接下来就是逆推导的过程,x‘=(x+m)%n  。

用数组记录胜利者所在的位置,a[1]表示剩有一个人时胜利者所在的位置,a[2]就是剩有两个人时胜利者所在的位置,由上面可知,a[1]=0。

以后的每一次删除就是重复上一次的过程,最后留下的人一定处于0号位置,那么可以一直递推上去求出胜利者一开始所在的位置。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 const int maxn = 10005;
 6 int a[maxn];
 7 
 8 int main()
 9 {
10     int n, k, m;
11     while (cin >> n >> k >> m && n && k && m)
12     {
13         memset(a, 0, sizeof(a));
14         for (int i = 2; i < n; i++)
15             a[i] = (a[i - 1] + k) % i;
16         int ans = (a[n - 1] + m) % n;
17         cout << ans+1 << endl;
18     }
19     return 0;
20 }

 

UVa 1394 约瑟夫问题的变形