LA 3882 经典约瑟夫环问题的数学递推解法
2014-02-26 14:46
591 查看
就是经典约瑟夫环问题的裸题
我一开始一直没理解这个递推是怎么来的,后来终于理解了
假设问题是从n个人编号分别为0...n-1,取第k个,
则第k个人编号为k-1的淘汰,剩下的编号为 0,1,2,3...k-2,k,k+1,k+2...
此时因为从刚刚淘汰那个人的下一个开始数起,因此重新编号
把k号设置为0,则
k 0
k+1 1
...
0 n-k
1 n-k+1
假设已经求得了n-1个人情况下的最终胜利者保存在f[n-1]中,则毫无疑问,该胜利者还原到原来的真正编号即为 (f[n-1]+k)%n (因为第二轮重新编号的时候,相当于把每个人的编号都减了k,因此重新+k即可恢复到原来编号)。由此,我们可以想象,当最终只剩下一个人的时候,该人即为胜利者,此时重新编号,因为只有一个人,所以此时f[1]=0
这样f[2]=(f[1]+k)%2,这样就可以求出最终胜利者在2个人的时候的情况下的编号,由递推公式f
=(f[n-1]+k)%n,可递推到最初编号序列中该胜利者的编号。
因此用这个方法,只需一遍On的扫描,即可求出最终答案
不过该题要求编号从1开始,只要把f
+1即可,同时,该题指定了第一个要删除的人必须为编号为m的人,其实也不难,求出f
之后,把原本编号为0的位置移到跟m只相距k的位置即可实现第一次删除的编号为m。所以最终 ans=(f
+1+m-k);
当然因为m-k可能为负数,导致整个ans为负,这样其实最后+n即可解决。
我一开始一直没理解这个递推是怎么来的,后来终于理解了
假设问题是从n个人编号分别为0...n-1,取第k个,
则第k个人编号为k-1的淘汰,剩下的编号为 0,1,2,3...k-2,k,k+1,k+2...
此时因为从刚刚淘汰那个人的下一个开始数起,因此重新编号
把k号设置为0,则
k 0
k+1 1
...
0 n-k
1 n-k+1
假设已经求得了n-1个人情况下的最终胜利者保存在f[n-1]中,则毫无疑问,该胜利者还原到原来的真正编号即为 (f[n-1]+k)%n (因为第二轮重新编号的时候,相当于把每个人的编号都减了k,因此重新+k即可恢复到原来编号)。由此,我们可以想象,当最终只剩下一个人的时候,该人即为胜利者,此时重新编号,因为只有一个人,所以此时f[1]=0
这样f[2]=(f[1]+k)%2,这样就可以求出最终胜利者在2个人的时候的情况下的编号,由递推公式f
=(f[n-1]+k)%n,可递推到最初编号序列中该胜利者的编号。
因此用这个方法,只需一遍On的扫描,即可求出最终答案
不过该题要求编号从1开始,只要把f
+1即可,同时,该题指定了第一个要删除的人必须为编号为m的人,其实也不难,求出f
之后,把原本编号为0的位置移到跟m只相距k的位置即可实现第一次删除的编号为m。所以最终 ans=(f
+1+m-k);
当然因为m-k可能为负数,导致整个ans为负,这样其实最后+n即可解决。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n,m,k; int main() { while (scanf("%d%d%d",&n,&k,&m)) { if (n+m+k==0) break; int s=0; for (int i=2;i<=n;i++) s=(s+k)%i; int ans; ans=(m-k+s+1)%n; if (ans<=0) ans+=n; printf("%d\n",ans); } return 0; }
相关文章推荐
- LA 3882 约瑟夫环(递推)
- 约瑟夫环问题数学解法
- 约瑟夫环问题数学解法
- 约瑟夫环问题数学解法
- 经典数学问题“鸡兔同笼”竟还有这种解法?
- 约瑟夫环问题的数学解法
- 约瑟夫环问题--递推解法
- 约瑟夫环问题【数学递推】【优化版】
- 约瑟夫环问题的数学解法
- 约瑟夫环问题的简单解法(数学公式法)
- 约瑟夫环问题的链表解法和数学解法(PHP)
- 约瑟夫环(约瑟夫问题的变形,LA 3882)
- 约瑟夫环问题的链表解法和数学解法(PHP)
- 约瑟夫问题变形 And Then There was One, LA 3882 递推 动态规划
- 求约瑟夫环问题最后胜利者的一般解法以及数学推导方法
- 约瑟夫问题变形 And Then There was One, LA 3882 递推 动态规划
- 约瑟夫问题的数学解法
- 约瑟夫环问题的Java版解法
- 链队的基本操作实现及约瑟夫环问题的队列解法
- 约瑟夫环问题--递归解法的理解