素数环
时间限制:1000 ms | 内存限制:65535 KB
难度:2
描述
有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。
输入
有多组测试数据,每组输入一个n,n=0表示输入结束。
输出
每组第一行输出对应的Case序号,从1开始。
如果存在满足题意叙述的素数环,从小到大输出。
否则输出No Answer。
样例输入
6
8
3
0
样例输出
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4
Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2
Case 3:
No Answer
根据题意,要求输出的每两个相邻的数的和为素数,且首尾相连的两个数的和也为素数。因为奇数和奇数相加不会是素数,偶数和偶数相加也不会是素数,所以想要输出满足题意的素数环就必须是奇偶相邻,所以n必须为偶数,但如果输入的n为1则输出为1。不知道我说的够不够明白,在代码中解释。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
#define maxn 22
int prime[110];//存放素数的数组
int a[maxn];//储存并更新排序后的数的序列
int visit[maxn];//用来记录第i个位置是否已经放置好位置
int cur;//代表当前所判断的数是第几个数
int n;
void isprime()//打表法将1到110之间所有的素数用1标记放入数组中对应位置,其余数用0标记
{
int i,j;
for(i=1;i<=110;i++)
prime[i]=1;
prime[1]=0;
for(i=2;i<=110;i++)
{
if(prime[i]==1)
{
for(j=2*i;j<=110;j+=i)
prime[j]=0;
}
}
}
void dfs (int cur,int n)
{
if(cur==n+1&&prime[1+a[n]])//如果当前判断的是第n+1个数,则证明前面所有的排序均符合题意,因为是环所以要判断首尾相加是否是素数
{
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
return ;
}
else
{
for(int i=2;i<=n;i++)//因为题目要求从1开始输出,所以判断时从2开始回溯
{
if(!visit[i]&&prime[i+a[cur-1]])//如果i没被用过且他和上一个数的和为素数,则往下执行
{
a[cur]=i;//将i储存开始判断下一个数
visit[i]=1;//标记i已经用过
dfs(cur+1,n);//继续对下一个数进行判断
visit[i]=0;//清除标志
}
}
}
}
int main()
{
int n,i,j,k=1;
isprime();
while(~scanf("%d",&n)&&n)
{
memset(a,0,sizeof(a));
memset(visit,0,sizeof(visit));
a[1]=1;
visit[1]=1;
printf("Case %d:\n",k++);
if(n==1)//如果n是1则自己成环输出1
printf("1\n");
else if(n%2!=0)//如果n为偶数,直接输出No Answer
{
printf("No Answer\n");
}
else
dfs(2,n);
}
return 0;
}