I looked at the problem and did not understand it. I put it on hold.
Joseph's ring problem (Joseph's)
The user inputs M and N values. The number of sequential loops starts from 1 to n. This value is output on every count to m until all are output. Write the C program. (Joseph's ring problem, Joseph's)
Solution 1 (my solution): idea: Create a circular linked list with n elements, and then traverse and count from the linked list header. If I = m (I was initially 1) start the element and continue the loop. When the current element and the next element exit the loop at the same time.
Code:
/* The user of the Joseph Ring problem (Joseph PHUs) Inputs M and N values, starting from 1 to n, the number of sequential loops. Each count to M outputs this value until all outputs are made. Write the C program. (Joseph Ring problem Joseph PHUs) Code by Eric Yang 2009 http://ericyang.cnblogs.com */# include <stdio. h> # include <stdlib. h> // chain table node typedef struct _ ringnode {int Pos; // location struct _ ringnode * Next;} ringnode, * ringnodeptr; // create Joseph ring, phead: linked List header pointer, Count: Number of linked list elements void createring (ringnodeptr phead, int count) {ringnodeptr pcurr = NULL, pprev = NULL; int I = 1; pprev = phead; while (-- count> 0) {pcurr = (ringnodeptr) malloc (siz EOF (ringnode); I ++; pcurr-> Pos = I; pprev-> next = pcurr; pprev = pcurr;} pcurr-> next = phead; // create a ring linked list} void printring (ringnodeptr phead) {ringnodeptr pcurr; printf ("% d", phead-> POS); pcurr = phead-> next; while (pcurr! = NULL) {If (pcurr-> Pos = 1) break; printf ("\ n % d", pcurr-> POS); pcurr = pcurr-> next ;}} void kickfromring (ringnodeptr phead, int m) {ringnodeptr pcurr, pprev; int I = 1; // count pcurr = pprev = phead; while (pcurr! = NULL) {if (I = m) {// kick out the ring printf ("\ n % d", pcurr-> POS ); // display the following steps: pprev-> next = pcurr-> next; free (pcurr); pcurr = pprev-> next; I = 1;} pprev = pcurr; pcurr = pcurr-> next; If (pprev = pcurr) {// The Last printf ("\ n % d", pcurr-> POS ); // display the free (pcurr); break;} I ++;} int main () {int m = 0, n = 0; ringnodeptr phead = NULL; printf ("--------------- Joseph Ring --------------- \ n"); printf ("N (person count) ="); scanf ("% d", & N ); printf ("m (out number) ="); scanf ("% d", & M); If (n <= 0 | M <= 0) {printf ("input error \ n"); System ("pause"); Return 0 ;}// create a linked table phead = (ringnodeptr) malloc (sizeof (ringnode )); phead-> Pos = 1; phead-> next = NULL; createring (phead, n); # ifdef _ debug printring (phead ); # endif // start outbound printf ("\ nkick order:"); kickfromring (phead, m); printf ("\ n"); System ("pause "); return 0 ;}
Solution 2 (from net): Thought: it is classified as a mathematical problem. The original article is very good. Copy it directly. Because the original author has not been found for half a day in the search, the reference address cannot be added. If this eldest brother sees this, please contact me, the younger brother immediately joins the reference link :)
Both using linked lists and array implementations have one thing in common: to simulate the entire game process, not only is it annoying to write programs, but also the time complexity is as high as O (Nm). When n, when M is very large (for example, millions or even tens of millions), there is almost no way to produce results in a short time. We noticed that the original problem only requires the serial number of the final winner, rather than simulating the whole process. Therefore, if efficiency is to be pursued, we must break the regular rules and implement some mathematical strategies.
To facilitate the discussion, change the problem slightly without affecting the original intention:
Problem description: N people (No. 0 ~ (N-1), reporting starts from 0, reporting ends from m-1), and reporting continues from 0. Calculate the number of the winner.
We know that after the first person (number must be M % N-1) is listed, the remaining n-1 person forms a new Joseph ring (starting with a person numbered K = m % N ):
K + 1 K + 2... N-2, n-1, 0, 1, 2,... K-2 and 0 from K.
Now let's convert their numbers:
K --> 0
K + 1 --> 1
K + 2 --> 2
...
...
K-2> N-2
K-1 --> n-1
After the transformation, it will completely become a subproblem of (n-1) the number of individual reports. If we know the solution of this subproblem: for example, X is the final winner, so it's just n people's situation to change X back Based on the table above ?!! The formula for changing back is very simple. I believe everyone can introduce it: x' = (x + k) % N
How can I solve the problem of (n-1) number of personal reports? Yes, as long as you know (n-2) the individual's solution. (N-2) What about personal solutions? Of course it is the first (n-3) situation ---- this is obviously a reverse push problem! Well, the idea is coming out. The recursive formula is as follows:
F [I] indicates that I personally play the game and report m to exit the number of the final winner. The final result is f [N].
F [1] = 0;
F [I] = (F [I-1] + M) % I; (I> 1)
With this formula, we need to calculate the value of F [I] From the 1-N order, and the final result is f [N]. Because the number in real life always starts from 1, we Output F [N] + 1
Because it is a step-by-step recursion, it does not need to save every f [I], and the program is also very simple:
#include <stdio.h>int main(){ int n, m, i, s = 0; printf ("N M = "); scanf("%d%d", &n, &m); for (i = 2; i <= n; i++) { s = (s + m) % i; } printf ("\nThe winner is %d\n", s+1);}