Contents
  1. 1. Problem Description
  2. 2. Input
  3. 3. Output
  4. 4. Sample Input
  5. 5. Sample Output

Problem Description

  某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。

Input

本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。

Output

共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。

Sample Input

2
20
40

Sample Output

1 7 19
1 19 37

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

queue <int> s;
//i=1(二) i=2(三) i=3(二) i=4(三) 所以,i是偶数则数到3踢人,否则数到2踢人
void solve(int k)
{

int i = 1;
while(s.front() != 0){
if(i % k != 0)
s.push(s.front()); //把留下来的放队尾
s.pop();
i++;
}
s.pop();
s.push(0); //把队首的0去掉,在队尾加上0
}

int main()
{

int t, n;
cin >> t;
while(t-- && cin >> n){
for(int i = 1; i <= n; i++)
s.push(i);
s.push(0); //编号是从1开始的,所以在最后面加个0代表队尾的标志
int i = 1;
while(s.size() > 4){ //因为加上了0,所以长度小于等于4就退出
if(i % 2 == 0) //选择数三下踢一个人还是数两下踢一个人
solve(3);
else
solve(2);
i++;
}
while(!s.empty()){
if(s.front() != 0){
cout << s.front();
s.pop();
if(s.front() != 0)
cout << " ";
}
else
s.pop(); //记得把队尾标志0也清空
}
cout << endl;
}
return 0;
}
Contents
  1. 1. Problem Description
  2. 2. Input
  3. 3. Output
  4. 4. Sample Input
  5. 5. Sample Output