UVa OJ 180 - Eeny Meeny

Time limit: 3.000 seconds
限時3.000秒ios

 

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的位置),不論實際候選人數是多少或是以何種方向計數(順時針或逆時針),該站位都是安全的。app

 

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),則輸入結束。less

 

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」。ide

 

Sample input
示例輸入

80 150
40 150
0 0
this

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個)。

對於任何一個肯定的候選人數有以三種狀況:1、最後剩下的人是Mxgobgwq,此時全部可能的位置都安全(注意題中兩次強調closest to Mxgobgwq,即Mxgobgwq的位置非可行解);2、候選人數爲偶數時剩下Mxgobgwq正對面的那我的,此時除去這我的的位置外的其餘全部可能的位置都安全;3、除以上兩種狀況外的其它狀況,會有兩個不安全的位置,但因爲圓圈的對稱性這兩個位置與Mxgobgwq的最短距離是相等的。綜上所述,對於任一種候選人數不安全的位置最多隻有一個,且安全的位置不能超過最少候選人數的一半。

對於一個估計的範圍,能夠創建一個標記數組,長度爲最少候選人數的一半,其每一個元素表明一個位置。全部元素初始化爲0,若對應位置被選中,則置1。最後從第1個元素(首元素爲第0個,此處需空過Mxgobgwq的位置)開始查找0,找到的第一個0的位置即爲所求。idea

 

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;}
相關文章
相關標籤/搜索