Title Description
Numbered from 1 to N, the N children playing game played in a loop. Children at the beginning of a circle of N, stand for the number of I + 1 number of children left I children. Number standing in a children number N of children left. First, number of children a start packet number, then the number of children standing order of packets to the left until the ring lies to a digital number M. Until only one child, the game is completed.
Now given N, M, find the children of the N ring sequence.
Input Format
The only line contains two integers N, M. (1 <= N, M <= 30000)
Output Format
The only line containing N integers, each of the two intermediate integers separated by a space, the I-th integer I-th number of children a circle
Sample
Sample input
5 3
Sample Output
3 1 5 2 4
简单来说,就是每次删除一个人,输出,继续循环一直输出到只剩最后一个人,输出。
如果要输出最后一个人,前面的输出直接省去就可以了
#include <the iostream> #include <cstdio> the using namespace STD; int main () { BOOL m [ 30001 ]; // save whether each person is still alive, alive to false, true dead int A, B; // A personal, b the ring CIN >> A >> b; for ( int I = . 1 ; I <= A; ++ I) m [I] = to false ; // all alive int C = 0 , D = 0 , E = 0 ; // D is the current number of packets do { ++C; IF (A + C == . 1 ) // If after the last one, back to the first, analog cyclic C = . 1 ; IF (m [C] == to false ) // If alive, reported number ++ D; IF (D == B) { D = 0 ; // zero COUT C << << " " ; // If just the last one, eliminating the need for m [C] = to true ; // that man was dead. . . . ++ E; } } the while(E = A!); // if dead, out }
This is a simple version of the above, the time complexity is O (n2)
The following is burning brain, ready to catch
Joseph problem 2 solved
Title Description
Joseph problem is a famous problem: N personal circle, the number of starting from the first report, the first of M will be killed, the last remaining one, the rest will be killed. Please write a program to determine the final number of people who will be left.
Input Format
Only input line for two integers n, m (0 <n, m <10 ^ 8).
Output Format
Only one line, a number, as the last remaining person's number
Sample
Sample input
6 5
Sample Output
1
这个问题你们看到了数据规模很大n2绝对超时
当N的值有上百万,M的值为几万时,到最后虽然只剩2个人,也需要循环几万次(M的数量)才能确定2个人中下一个出列的序号。显然,在这个程序的执行过程中,很多步骤都是进行重复无用的循环。现在有一个强大的数学规律
解析:
其中,在约瑟夫环中,只是需要求出最后的一个出列者最初的序号,而不必要去模拟整个报数的过程。因此,为了追求效率,可以考虑从数学角度进行推算,找出规律然后再编写程序即可。
我们从0开始循环(从零开始报数),到n-1,共n个人,第一个出圈的人是报数m-1的,所以他的编号是m-1或(m-1)%n(因为是从零开始,所以不用考虑+1问题)
现在有n-1个人,从0循环到n-2(已经出圈的人的空位删掉),报数现在(删掉空位后)从(m-1)%n报0,1,2,3,4...。(m-1+(m-1)%n
)%(n-1)出圈,每一次都模现在的人数。
实际上就是一层层的模
现在我们逆推,假设现在只剩下1人,出圈的肯定是0号。
设f=0,f是最后活的那个人在只剩下一个人的环中的编号
现在进入两个人的环,报m-1的出圈,他就是当时的第m个,所以他在两个人的圈中的编号就是f+m,由于人数可能少于m,所以要用模,f=(f+m)%n n=2;
然后进入三个人的圈,m-1继续出圈,他是第m个,在上一圈里,他是f,所以f=(f+m)%n n=3;
以此类推,n=4,5,6,7,8......
因为题中是从1开始报,所以在算出n个人的圈中,那个人的编号f后,要+1;
程序很简单,一个循环就搞定;
#include <the iostream> the using namespace STD; Long Long n-, m, F; // automatically assigned zero outside int main () { CIN >> >> n- m; for ( int I = 2 ; I <= n-; ++ i) // with i count the number F = (F + m)% i; F ++ ; COUT << F; }
Little insight, the god of exhibitions