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 }