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

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


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


Sample Input

2 20 40

Sample Output

1 19 1 19 37

#include<iostream>
#include<queue>
#include<vector>
using namespace std;

int main()
{
int n,t,flag,num;
cin>>t;
while(t--)
{
queue<int>Q1,Q2; //定义两个队列
cin>>n;

for(int i=1;i<=n;i++)
Q1.push(i);

if(Q1.size()<=3) //若总数小于3直接输出
{
cout<<Q1.front();
Q1.pop();
while(!Q1.empty())
{
cout<<" "<<Q1.front();
Q1.pop();
}
cout<<endl;
continue;
}

while(1)
{
num=1;
flag=2; //mod2
while(!Q1.empty()) //将序号不为2的倍数的放入另一个队列
{
if(num%flag!=0)
{
Q2.push(Q1.front());
}
Q1.pop();
num++;
}
if(Q2.size()<=3) //若放完后总数小于等于3,输出
{
cout<<Q2.front(); //注意输出格式,不能输出多余空格
Q2.pop();
while(!Q2.empty())
{
cout<<" "<<Q2.front();
Q2.pop();
}
break;
}

num=1;//剩下的向小序号方向靠拢,继续从头开始进行
flag=3;
while(!Q2.empty()) //同上
{
if(num%flag!=0)
{
Q1.push(Q2.front());
}
Q2.pop();
num++;
}
if(Q1.size()<=3)
{
cout<<Q1.front();
Q1.pop();
while(!Q1.empty())
{
cout<<" "<<Q1.front();
Q1.pop();
}
break;
}
}
cout<<endl;
}
return 0;

}

其他方法:

#include <iostream>
using namespace std;
int main() {
int n, t;
cin >> t;
while (t--) {
int n;
cin >> n;
if(n<=3) { //如果人数少于3 直接输出 这点要注意 容易被忽略
if(n == 1) cout<<"1"<<endl;
if(n == 2) cout<<"1 "<<"2"<<endl;
if(n==3)
cout<<"1 "<<"2 "<<"3"<<endl;
} else {
int a[5000];
for (int k = 0; k <= n; k++) //首先每个人设为1
a[k] = 1;
int b = 2, l = n, j = 0; //第一轮是报到二的出列
for (int i = 1; i <= n ; i++) {

if (a[i]) { // 没有出列的进行报数
j++;
if (j == b) { //报到b 出列 设为0
a[i] = 0; //已经出列的设为0
j = 0;

}
}
if (i == n) { //一轮已经报完 重新开始
l -= (l / b); // 总人数没一轮会减少l/b
if (l <= 3) break;

if (b == 2) b = 3; // b 要改变
else b = 2;
i = 0;
j = 0;

}

}
int w = 0;
for (int h = 1; h <= n; h++) //从新开始找如果为一就是没有出列的人 输出
if (a[h]) {
w++;

cout << h;
if(w<l)cout<<" ";
else cout<<endl;
}
}
}
return 0;
}