素数环
-
描述
-
有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。
为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。
-
输入
- 有多组测试数据,每组输入一个n(0<n<20),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
来源
代码实现:
#include<stdio.h>
#include<math.h>
#include<string.h>
int is_prime(int n)//为素数则返回1,非素数返回0
{
int i,k=sqrt(n);
for(i=2;i<=k;i++)
if(n%i==0)break;
if(i>k)
return 1;
else return 0;
}
int isp[200],a[200],vis[200];
void dfs(int cur,int n)//深度优先搜索
{
int i;
if(cur==n&&isp[a[0]+a[n-1]])
{
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
else for(i=2;i<=n;i++)
{
if(vis[i]==0&&isp[i+a[cur-1]])
{
a[cur]=i;
vis[i]=1;
dfs(cur+1,n);
vis[i]=0;
}
}
}
int main()
{
int n,e=0,i;
scanf("%d",&n);
while(n!=0)
{
printf("Case %d:\n",++e);
if(n%2&&n!=1)printf("No Answer\n");
else{
for(int j=1;j<=2*n;j++)
isp[j]=is_prime(j);
a[0]=1;
isp[0]=1;
dfs(1,n);
}
scanf("%d",&n);
memset(a,0,sizeof(a));
}
return 0;
}
/*
学会的第一种求素数环的方法,虽然运行超时了!
#include<stdio.h>
#include<math.h>
int a[21],n,flag;//flag变量用来标记是否找到过素数环
int swap(int n,int i)//交换a[i]和a[n]用的,不是交换i和n。
{
int t;
t=a[i];
a[i]=a[n];
a[n]=t;
}
void print(int a[])//用于输出找到的素数环
{
int i;
for(i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
int is_prime(int k)//判断一个数是不是素数用
{
int i,j;
j=(int)sqrt(k);
for(i=2;i<=j;i++)
if(k%i==0) return 0;
return 1;
}
void search(int m)//递归搜素
{
int i;
if(m>n)//已经搜索到了边界
{
if(is_prime(a[n]+a[1])) //当已经搜索到叶结点时,表示最后一个和他前面的也判断过了,再判断如果第一个和最后一个首位相接也是素数,则输出。
{
print(a);
flag=1;
}
else return;
}
else
{
for(i=m;i<=n;i++)
{
swap(i,m);//判断a[m-1]+a[m]是否是素数
if(is_prime(a[m-1]+a[m])) search(m+1);//递归搜索下一个位置
swap(i,m);//重新把a[m]和a[i]换回来
}
}
}
int main()
{
int k=1,i;
while(scanf("%d",&n),n)
{
flag=0;
for(i=1;i<=n;i++)
a[i]=i;
printf("Case :%d\n",k++);
search(2);
if(flag==0) printf("No answer\n");
}
return 0;
}
*/