poj 1012 Joseph (约瑟夫问题)

Joseph

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 47657   Accepted: 17949

Description

The Joseph‘s problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved.
Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved.

Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.

Input

The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.

Output

The output file will consist of separate lines containing m corresponding to k in the input file.

Sample Input

3
4
0

Sample Output

5
30

Source

约瑟夫问题的变形,开始对题意就理解了好久,这类题目主要要找到中间的公式;这道题就要知道 当前出局的位置 = (前一个出局的位置+m-1)%(2k-(k-1);

是从0开始数,这就是一个通式;明白了这个公式这个题相当于就做出了一半;这中间还有一个判别的条件,就是如果当前的位置如果<k,说明这种情况就不满足了;

第一种方法:就直接可以对m的值进行枚举,利用判别条件,找出合适的m值;

下面是代码;这种思路好像200ms可以过;

//暴力+枚举
#include <cstdio>
#include <cstring>
int main()
{
    int k;
    int ans[20];//储存当前的位置
    int Joseph[20]={0}; //储存符合条件的m的值
    for(k=1;k<14;k++)
    {
        int m=1;
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=k;i++)
        {
            ans[i]=(ans[i-1]+m-1)%(2*k-i+1); //递推公式
            if(ans[i]<k)
            {
                i=0;
                m++;
            }
        }
        Joseph[k]=m;
    }
  while(scanf("%d",&k)&&k!=0)
   {
       printf("%d\n",Joseph[k]);
   }
   return 0;
}

要想0ms过的,直接得出结果数组,然后再提交;

//直接枚举 0ms
#include <cstdio>
#include <cstring>
int main()
{
    int k;
  int Joseph[]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,1245064};
  while(scanf("%d",&k)&&k!=0)
   {
       printf("%d\n",Joseph[k]);
   }
   return 0;
}

第二种方法,要挖掘题目中的隐含条件,我看了好久都没看出来,代码是参考别人的,这种46ms就可以过;优化了不少;

题目中的隐含条件;只剩下一个坏人的时候,下一个报数的人要么是第1个人,要么是第k+1个人;所以间隔就是m=s*(k+1)或者是 m=s*(k+1)+1;

粗略的证明一下,参考别人的:(这里我也还有点没懂)

仅剩一个坏人,圈长为k+1;设下一个报数人为第一个人时的时间间隔为m1;下一个报数人为第k+1个人时的时间间隔为m2;

由 (1+m1)%(k+1)=1 得出 m1= s*(k+1);

   (k+1+m2)%(k+1)=1  得出 m2=s*(k+1)+1;

这样我们就可以对m的枚举优化剪枝,m是(k+1)的倍数或者是他的倍数+1;

#include <cstdio>
#include <cstring>
bool Joseph(int k,int m)
{
    int n=2*k,x=0;
    while(n>k)
    {
        x=(x+m-1)%n;//递推公式,算出当前出局的位置
        if(x<k) //判别条件
            return false;
        n--;
    }
    return true;
}
int main()
{
    int k;
    int result[20]={0};
    for(k=1;k<14;k++)
    {
        for(int i=k+1;;i+=k+1) //对m枚举进行优化
        {
            if(Joseph(k,i)) //m是k+1的倍数或者倍数+1
            {
                result[k]=i;
                break;
            }
            else if(Joseph(k,i+1))
            {
                result[k]=i+1;
                break;
            }
        }
    }
    while(scanf("%d",&k)&&k)
    {
        printf("%d\n",result[k]);
    }
}

总结一下:对于这一类题型要读懂题目的题意,挖掘题目的隐含条件,多构思,理清思路才开始动手写。

时间: 2024-12-26 18:39:52

poj 1012 Joseph (约瑟夫问题)的相关文章

POJ 1012 Joseph 变形约瑟夫环

子问题与原问题........ 题意: 有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k) 现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去.问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉? PS:当前一轮第m个人死去后,下一轮的编号为1的人 为 前一轮编号为m+1的人. 前一轮恰好是最后一个人死掉,则下一轮循环回到开头那个人报"1" 这道题起初看以为是道模拟题,因为数据结构课上写过.但是必然超时····到11的时

NYOJ 191 &amp;&amp; POJ 1012 Joseph(约瑟夫环问题)

链接:click here~~ 题意:假设有2k个人围着一个圆桌坐着,前k个是好人,后k个是坏人 .现在开始,每m个人踢掉一个,比如有6个人,m=5,那么,被踢掉的人依次是5,4,6,2,3,1.现在要求,在踢掉第一个好人前,必需把所有的坏人踢掉,问,给定一个k,求满足这个要求的最小的m,现在希望你写一个程序,快速的帮助小珂,计算出来这个m. 思路:我们来回想一下最基本的约瑟夫环问题, n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数.求最后余下的人编号

POJ 1012 Joseph

Joseph Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 53862   Accepted: 20551 Description The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n,

POJ 1012 Joseph 推导,暴力,约瑟夫环,打表 难度:2

http://poj.org/problem?id=1012 答案以954ms飘过,不过这道题可以轻松用打表过 思路:如果我们把每个人位于数组中的原始编号记为绝对编号,每次循环过后相对于绝对编号为0的人的编号为相对编号,那么在这道题里,绝对编号是不重要的,只需要每次相对编号n都落在n>=k的位置上,那么n轮后自然所有的bad boy都被处理了. 而相对编号的推导: 设 id[i]为第i轮点到的编号(i从1开始计数),第i+1轮开始时存在的人数就会是2*k-i,点到的人的编号就是(id[i]+m-

POJ 1012 Joseph(打表题)

题意:约瑟夫环的变形.要求寻找到一个杀人循环节m使后半节的坏人先被所有杀光. 直接链表模拟出结果,再打表即可: 代码:(凝视的是打表码) #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<string> #include<cstring> #include<algorithm> u

poj 1012 &amp; hdu 1443 Joseph(约瑟夫环变形)

题目链接: POJ  1012: http://poj.org/problem?id=1012 HDU 1443: http://acm.hdu.edu.cn/showproblem.php?pid=1443 约瑟夫环(百度百科): http://baike.baidu.com/view/717633.htm?fr=aladdin Description The Joseph's problem is notoriously known. For those who are not famili

poj 1012——Toseph

提交地址:http://poj.org/problem?id=1012 Joseph Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 52098   Accepted: 19839 Description The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from amon

POJ 2800 Joseph&#39;s Problem

给n 和 k 求: ∑1<=i<=n(k mod i). p  = k/i k mod i = k - p * i k mod ( i + 1 ) = k - p * ( i + 1 ) = k mod i - p k mod ( i + 2 ) = k - p * ( i + 2 ) = k mod i - 2 * p 对于连续的 i ,很多p都是一样的 . 相差的部分是一个等差数列 , i 的 范围是 从 i 到 min(k/p,n) 如果 p == 0 则 一直延续到最后 Joseph'

POJ 1012:Joseph

Joseph Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 50068   Accepted: 19020 Description The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n,