问题描述:1,2,3,4,5,6,站成一排,从一开始,每次数3个数,数到的数被移除,将移除的数按先后顺序输出,得到一个排列,这样就能得到最后一个被移除的数。以下这个程序输入整数n和m,其中n为一数组的大小,m表示数几个数;
程序代码如下:
#include <iostream>
#include <stdio.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int main() {
int i,j,k,n,l,m;
while((cin>>n>>m)&&(n!=0)&&(m!=0)){
int a[20]={0};
int jos[20]={0};
for(i=0;i<n;i++){
a[i]=i+1;
}
l=n;k=0;
for(i=0;i<n;i++){
k=(m+k-1)%l; //得到被移除的数的位置,是下标;
jos[i]=a[k]; //保存被移除的数;
for(j=k;j<n-1;j++){ //将被移除的数覆盖,数组整体少一位;
a[j]=a[j+1];
}
l--;
}
for(i=0;i<n;i++){
printf("%d ",jos[i]);
}
cout<<endl;
}
cout<<endl;
return 0;
}
结果如下:
另外做了POJ的1012描述的也是joseph,只不过为逆推过程,问题描述为:一个排列内有k【1,k】个好人和k【k,k+1】个坏人,在好人被移除前,坏人先被移除,如一组数列1,2,3,4,5,6;当从5数时,则被移除的顺序为:5,4,6,2,3,1,满足条件。所以当输入k为3时,输出m为5;
程序代码如下:
<strong><span style="font-size:18px;">#include <iostream>
using namespace std;
int main() {
int n,m,i,k;
while(cin>>k && k!=0){
n=2*k;
m=1;
int a[20]={0};
for(i=1;i<=k;i++){
a[i]=(a[i-1]+m-1)%(n-i+1); //若m=n,则a[i]=0,所以有a[i-1]+m-1,当然在判断时,a[i]<k;
if(a[i]<k){ //由于上式中a[i]的到的值比实际上少一,另外累加m找到合适的m;
m++;
i=0;
}
}
cout<<m<<endl;
}
return 0;
}</span></strong>
输出结果如下: