题目描述
Xerxes 在和他的同学们做一个游戏,游戏规则如下:
最开始的时候 n 个人站成一排,编号为 1,2,3,4,…
每一轮编号为质数的同学将会被标记,这一轮过后被标记的同学将会从这一排中离开。
在每一轮一些同学离开后,剩余的同学将会按照编号从小到大的顺序重新从 1开始编号,如果有一轮结束后这一排中剩下的同学个数小于 4,那么游戏结束,剩下的所有人将会赢得游戏。
例如,n=10开始的时候:
1 2 3 4 5 6 7 8 9 10
第一轮游戏过后,编号为 2,3,5,7的同学将会离开,这一排变为(以下编号为最开始的编号):
1 4 6 8 9 10
下一轮,原来编号为 4,6,9的同学将会离开,因为他们的新编号为 2,3,5,是质数.
最后,这一排变为(以下编号为最开始的编号):
1 8 10
共 3人,少于 4人,因此游戏结束,最开始编号为 1,8,10的同学赢得了游戏。
当人数比较多的时候,Xerxes 感觉游戏过程太长了,因此他希望你能帮他写一个程序,来求出当开始有 n 人的时候最后获胜的是哪几个同学,并输出他们的最开始的编号。
输入
一个数 n(3<n≤200)表示初始人数.
输出
一行若干个数(不超过 3 个),表示最终获胜的同学的初始编号.
输入输出样例
样例输入 #1
10
样例输出 #1
1 8 10
样例输入 #2
15
样例输出 #2
1 14
参考解答
//2022.10.30
//2022.12.2添加注释
#include<stdio.h>
#include<math.h>
int isprime(int x)//判断素数
{
int i;
if(x<2)
return 0;
if(x==2)
return 1;
for(i=2;i<x;i++)
if(x%i==0)
return 0;
return 1;
}
int game(int a[],int n)
{
int cnt=0;
for(int i=2;i<=n;i++)
{
if(isprime(i)==1)//判断是否是素数
{
a[i]=0;//将素数的位置标记为0
cnt++;//计数器加一
}
}
if(a[2]==0)//如果两个删去的素数位置连续,后面的数向前移一遍
for(int j=2;j<=n;j++)
a[j]=a[j+1];
for(int k=2;k<=n;k++)
if(a[k]==0)
for(int j=k;j<=n;j++)
a[j]=a[j+1];//将删去的数后面的数前移
n-=cnt;//总数减去计数器得到一遍游戏后剩下的人数
return n;
}
int main()
{
int n;
scanf("%d",&n);
int a[n+1];
for(int i=1; i<=n; i++)
a[i]=i;
while(n>3)//判断每次游戏过后剩下的人数是否小于3
n=game(a,n);
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);//输出最后胜出人的编号
}
return 0;
}