题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83498#problem/C
题意:
将新兵从一开始按顺序依次编号,并排成一行横队,从头开始一至二报数,凡报到二的出列,剩下的靠拢,再从头开始进行一至三报数,凡报到三的出列,剩下的靠拢,以后从头开始轮流进行一至二报数、一至三报数直到剩下的人数不超过三人为止。 输出最初编号。
案例:
input
2
20
40
output
1 7 19
1 19 37
思路分析:
循环进行,循环条件为n>3;
每次循环先报二再报三,报二时记为偶数,则报三是为奇数,首先判断是报二,还是报三。
报二时把不报二的数重新存到数组中,人数n=n-n/2;
报三时把不报三的数重新存到数组中,人数n=n-n/3;
判断剩下的人数n,输出数组中前个数。
源代码如下:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int main() 5 { 6 int N; 7 cin>>N; 8 while(N--) 9 { 10 int n,s=1,a[5010],k,i; 11 cin>>n; 12 for(i=1;i<=n;i++) 13 a[i]=i; 14 while(n>3) 15 { 16 s++; 17 k=2; 18 if(s%2==0) //报二 19 { 20 for(i=3;i<=n;i++) 21 if(i%2!=0) //判断不报二的人,重新存入数组 22 { 23 a[k]=a[i]; 24 k++; 25 } 26 n=n-n/2; 27 } 28 else //报三 29 { 30 for(i=2;i<=n;i++) 31 if(i%3!=0) //判断不报三人,重新存入数组 32 { 33 a[k]=a[i]; 34 k++; 35 } 36 n=n-n/3; 37 } 38 } 39 if(n==3)printf("%d %d %d ",a[1],a[2],a[3]); 40 if(n==2)printf("%d %d ",a[1],a[2]); 41 if(n==1)printf("%d ",a[1]); 42 } 43 return 0; 44 }