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 nSizeMin, nSizeMax; std::cin >> nSizeMin >> nSizeMax;) {
        if (nSizeMin > nSizeMax)
            std::swap(nSizeMin, nSizeMax);
        if (nSizeMin == 0 && nSizeMax == 0)
            break;
        std::vector<int> vecCover(nSizeMin / 2, 0);
        for (int nSize = nSizeMin, 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章