UVa OJ 180 - Eeny Meeny

Time limit: 3.000 seconds
限时3.000秒

Problem
问题

In darkest <name of continent/island deleted to prevent offence> lived a tribe called the ``Eeny Meenys''. They got this name from their way of choosing a chief for a year. It appears that a newspaper reporter visited the tribe and managed to get across a few ideas of civilisation, but apparently came to an unfortunate end before finishing the job. Thus the tribe no longer had a permanent chief; the chief's term was exactly one year. At the end of that time, they ate the current chief, and chose another chief. Their method of choosing a chief was the ``Eeny meeny miny mo'' method. All eligible tribal members (women were also eligible--one of the blessings of civilisation the tribe had adopted) stood in a circle, a starting place was chosen, and the chief medicine man (who was ineligible for chieftainship) went around counting out `E', `e', `n', `y', `M', `e', `e', `n', `y', `M',`i', `n', `y', `M', `o!', `E', `e', `n', `y', `M', `e', `e', `n', `y', `M', `i', `n', `y', `M', `o!', .... At every `o!', the person indicated was pushed out of the circle which then closed up and the count restarted with his neighbour (the one who would have been `E' anyway). This process continued until only one was left--the new chief.
在darkest(为岛或者大陆的名字,为防止被攻打已将其删除)上定居着一个名为“Eeny Meenys”的部落。这个部落名字的由来跟他们每年选举部落首领的方式有关。听说有一个新闻记者走访了该部落,并尝试将一些现代文明带给他们,然而不幸的结局使他的工作永远无法完成。因此该部落不再具有永久的首领;首领的任期只有一年。首领的任期结束后就会被人们将吃掉,然后重新选择首领。他们选择首领的方式名叫“Eeny meeny miny mo”,具体是:所有合格的部落成员(女性也有资格——部落文明之一)站成一个圈,选定一个起始位置,然后大巫师(他没有参选资格)开始绕圈计数‘E’,‘e’,‘n’,‘y’,‘M’,‘e’,‘e’,‘n’,‘y’,‘M’,‘i’,‘n’,‘y’,‘M’,‘o!’,‘E’,‘e’,‘n’,‘y’,‘M’,‘e’,‘e’,‘n’,‘y’,‘M’,‘i’,‘n’,‘y’,‘M’,‘o!’……每一次在‘o!’这个位置上的人将被推出圈外,然后闭合圆圈,从他的邻居(将被点到‘E’的那个人)重新开始计数。照此方法执行,直到剩下一个人,即被选为首领。

While the chance of glory for a year makes the job of chief highly attractive to tribal members, you (possessing a computer decades before they were invented) find the brevity of the glory unappealing. You have managed to find out that the count this year will start with Mxgobgwq (a very large person), so you would like to know where not to stand. You don't know the direction, nor how many eligible people there are, but you can estimate the number (it is certainly less or equal than 1000000).
尽管一年任期的首领职位强烈地吸引着部落成员,但这短暂的荣耀并不能让你(你拥有一台几十年后才会发明出来的电脑)产生兴趣。你已经搞清今年的计数将从Mxgobgwq(一个非常高大的人)开始,你还想知道不能站在哪个位置。你不清楚计数的方向,也不清楚候选人数,但是你能估计到候选人数的范围(一定是小于或等于1000000的数)。

Write a program that will determine the `first' (i.e. closest to Mxgobgwq) safe position to stand, regardless of the actual number of people and the direction of count (clockwise or anti-clockwise).
写一个程序来确定第一个站立位置(即最靠近Mxgobgwq的位置),不论实际候选人数是多少或是以何种方向计数(顺时针或逆时针),该站位都是安全的。

Input
输入

Input will consist of a series of lines, each line containing the upper and lower estimates of the number of eligible people (both numbers inclusive). The file will be terminated by a line containing two zeroes (0 0).
输入由一系列的行组成,每一行包含估计候选人数的上界和下界(包含边界值)。若一行输入两个0(0 0),则输入结束。

Output
输出

Output will consist of a series of lines, one for each line of the input. Each line will consist of a single number giving the number of the position closest to Mxgobgwq that will not be chosen as chief for any number in the given range and for either direction of elimination. If no position is safe then print "Better estimate needed".
输出由一系列的行组成,每一行对应一行输入。每一行为一个数,该数表示对于估计候选人数范围内的每一个数,不论从哪个方向计数都不会被选为首领,且最靠近Mxgobgwq的位置。如果不存在这样的安全位置,则输出“Better estimate needed”。

Sample input
示例输入

80 150
40 150
0 0

Analysis
分析

人们站一个圈,每隔15个排除一个,直到剩下最后一个,这显然是典型的约瑟夫问题。约瑟夫问题的求解详见*:Josephus problem
这里使用递归式:g(n,k)=(g(n-1,k)+k)mod n, g(1,k)=0进行求解。

Mxgobgwq就是开始计数的位置,我们定为0。由于计数的方向不定,对于某一个确定的候选人数,安全的位置只能以“离Mxgobgwq有多远”来表示。任何大于估计的最少人数一半的安全位置都是没有意义的。比如估计的最少人数是10,而算出的安全位置是8(从0开始编号),那么当实际的人数为10时,你的站位就变成了2(顺时针计数Mxgobgwq右边第8个即逆时针计数的左边第2个)。

对于任何一个确定的候选人数有以三种情况:一、最后剩下的人是Mxgobgwq,此时所有可能的位置都安全(注意题中两次强调closest to Mxgobgwq,即Mxgobgwq的位置非可行解);二、候选人数为偶数时剩下Mxgobgwq正对面的那个人,此时除去这个人的位置外的其他所有可能的位置都安全;三、除以上两种情况外的其它情况,会有两个不安全的位置,但由于圆圈的对称性这两个位置与Mxgobgwq的最短距离是相等的。综上所述,对于任一种候选人数不安全的位置最多只有一个,且安全的位置不能超过最少候选人数的一半。

对于一个估计的范围,可以建立一个标记数组,长度为最少候选人数的一半,其每个元素代表一个位置。所有元素初始化为0,若对应位置被选中,则置1。最后从第1个元素(首元素为第0个,此处需空过Mxgobgwq的位置)开始查找0,找到的第一个0的位置即为所求。

Solution
解答

#include <algorithm>
#include <iostream>
#include <vector> typedef std::vector<int>::iterator VECINT_ITER; int Josephus(int n, int k)
{
    static std::vector<int> vecJosephus(1, 0);
    if (n <= (int)vecJosephus.size())
        return vecJosephus[n - 1];
    int j = (Josephus(n - 1, k) + k) % n;
    vecJosephus.push_back(j);
    return j;
} int main(void)
{
    for (int i = 0; i < 100000; Josephus(++i, 15));
    for (int nSi*, nSizeMax; std::cin >> nSi* >> nSizeMax;) {
        if (nSi* > nSizeMax)
            std::swap(nSi*, nSizeMax);
        if (nSi* == 0 && nSizeMax == 0)
            break;
        std::vector<int> vecCover(nSi* / 2, 0);
        for (int nSize = nSi*, nJump = 15; nSize <= nSizeMax; ++nSize) {
            int j = Josephus(nSize, nJump);
            if (j > nSize / 2)
                j = nSize - j;
            if (j < vecCover.size())
                vecCover[j] = 1;
        }
        VECINT_ITER ir = std::find(vecCover.begin() + 1, vecCover.end(), 0);
        if (ir == vecCover.end())
            std::cout << "Better estimate needed" << std::endl;
        else
            std::cout << ir - vecCover.begin() << std::endl;
    }
    return 0;
}
上一篇:Mysql事务探索及其在Django中的实践(二)


下一篇:Java ,python面向对象的继承及其区别