本题可以视为约瑟夫问题的弱化版本,即不构成闭环结构,是断裂的线组合
本题有三个值得注意的点:
1.在进行淘汰时,需要考虑到不一定跑完了单次循环,例如卡牌为2,可能淘汰完2,4后就符合要求了,不需要淘汰6。即需要把循环结束条件放到小循环中,随时监测剩余的值。这种情况在卡牌值为1时表现的很明显,因为每一个数都可以被淘汰,故什么时候结束淘汰就与剩余人数相关性很大了。
2.本题采用了结构体的方式,储存其原始位与改变位,其实原始位可以用数组下标来替代,由此可以避开使用结构体,但是这里还是选用了结构体,目的在于展现结构体的强大之处,可以储存一个对象的多项指标,在有更复杂的排序,淘汰规则时,就必然会派上用场了。
3.本题通过将淘汰出局的项的序号标记为-1来记录出局项,这里有一个很容易忽略的点,就是淘汰掉一项后,在对序列重新赋值后,下一轮进入判断是否淘汰的对象不能包括上一轮被淘汰的对象,即a[i].seq!=-1,如果没有这一项判断,那么minusnum的计算就会出现错误,会多算一部分数据,导致函数提前结束,输出项变多
#include <iostream>
using namespace std;
int main()
{
int n,minusnum=0,x;
cin>>n>>x;
struct{
int num;
int seq;
}a[n];
int i;
for(i=0;i<=n-1;i++){
a[i].num=i+1;
a[i].seq=i+1;
}
int b[20];
for(i=0;i<=19;i++){
cin>>b[i];
}
int j=0,p;
do{
if((n-minusnum)<=x)break;
for(i=0;i<=n-1;i++){
if((a[i].seq)%b[j]==0&&a[i].seq!=-1) {
a[i].seq=-1;
minusnum++;
}
if((n-minusnum)<=x) break;
}
p=1;
for(i=0;i<=n-1;i++){
if(a[i].seq!=-1){
a[i].seq=p;
p++;
}
}
j++;
}while(1);
for(i=0;i<=n-1;i++){
if(a[i].seq!=-1){
cout<<a[i].num;
break;
}
}
int u;
for(u=i+1;u<=n-1;u++){
if(a[u].seq!=-1){
cout<<' '<<a[u].num;
}
}
return 0;
}