[Analog linked list] Joseph

Joseph

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1652    Accepted Submission(s): 1031


Problem 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
 

Ideas:

If you use the list of C++STL to do this question, it will time out. I have not thought of how to use the list in the AC question. The method used here is to simulate the process of a linked list. The idea is simply to enumerate the values ​​of m one by one. Output m until the conditions are met, but if you use a list, every time you delete a list element, you need to traverse the entire list. Generally, thousands of times of traversal will take a lot of time. Therefore, the way to not time out is to skip the traversal. , directly by finding the element after + m, and then deleting it, every time you enumerate an m value, you only need to traverse k elements, and the time will be much faster; there is another point to pay attention to, similar to the future. The question should be habitually adding an array of punching tables to avoid the time-out of multiple input times of the judgment machine. The code is given below (the simulation method will be given below the code)

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<time.h>
#include<cmath>
#include<stack>
#include<list>
#include<queue>
#include<map>
#define E exp(1)
#define PI acos(-1)
#define mod (ll)(1e9+9)
#define INF 0x3f3f3f3f;
//#define _CRT_SECURE_NO_WARNINGS
//#define LOCAL
using namespace std;

typedef long long ll;
typedef long double lb;


int main(void)
{
#ifdef LOCAL
	freopen("data.in.txt", "r", stdin);
	freopen("data.out.txt", "w", stdout);
#endif
	//The above content can be ignored, it is the spare code for doing the question
	int k,tp, cnt, num, flag, table[15];
	memset(table, 0, sizeof(table));

	while (scanf("%d", &k) != EOF) {
		if (k == 0) break;

		if (table[k] != 0) { //The array of the table is to save the obtained answer,
			printf("%d\n", table[k]); //Determine the next multiple sets of data measured by the machine, if it is the requested data
			continue; //Then it can be output directly
		}

		int m = k + 1, cur;
		// Nothing related to the linked list is used here, just at the end of the for loop,
		//Add an if (to the last value) to let i = 0 traverse again,
		//This is like traversing a linked list  
		while (1) {
			num = 2*k; flag = 0; why = 1;
			while (num > k) {
				// The value of this tp is the number of times the current traversed value cur continues to count,
				//In fact, there is no problem in changing tp to m,
				//It's just that once the value of m is large, it will take a lot of time
				//For example, m = 10 to count in an array with 6 elements,
				//The result of reporting 10 times and reporting 4 times is the same,  
				tp = m % num == 0 ? num : m % num	 

				//The value of the next cur here is obtained through two situations, the first is after the number of tp is reported
				//If there is no more than the current number of elements, you can directly +tp
				// If it exceeds, find the next cur through the complementary relationship
				if (cur + tp - 1 > num) {			
					cur = tp - (num - cur)-1; //cur for the complementary relationship
				}									
														
				else cur = cur + tp - 1;

					if (cur <= k) {
						flag = 1;
						break;
					}
					else num--;
				}
			if (flag) {
				m++;
				//Here is a pruning code when enumerating m, if the result of the first report
				// Less than or equal to the value of K, then this number does not need to be tried, directly use the current enumeration value
				//Add to a value greater than k and then try
				if (m % (2 * k) <= k && m % (2 * k) != 0) {
					m += (k - m % (2 * k) + 1);			
				}
			}
			else{
				table[k] = m;
				printf("%d\n", m);
				break;
			}
		}
	}	
	//system("pause");
	return 0;
}

The simulation process here is roughly like this:

When m = 5 , k = 3

1 2 3 4 5 6 After reporting the number 5, according to the method of the linked list, the element 5 is deleted, but this is not the case, but the position of 5 is given to 6.

The result is this:

1 2 3 4 5   

Then there are currently 5 elements, find tp according to the method in the code and start counting from the element 5, cur will be the element 4, then the position of the element 4 is set to 5 (that is, the previous element of the element to be deleted) ), the deletion process is very simple, that is, set a num = 2*k before the traversal; as long as num-- can not continue to traverse the numbers of the array larger than num;

Then the result is 1 2 3 4 , continue to count, and finally get cur = 3, at this time num==k then you can exit the loop;




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324760787&siteId=291194637