NYOJ_488题 素数环 的经验之谈

素数环

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 2
描述

有一个整数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

/*************************************************************************
  > File Name: PrimeRing.cpp
  > Author: SSW
  > Mail: alisin520@gmail.com 
  > Created Time: Mon 28 Jul 2014 15:51:12 CST
 ************************************************************************/

#include<iostream>
#include<string.h>
#include<stdio.h>
#define N 25
using namespace std;
bool isp[2*N];

bool is_prime(int n){
	if(n <= 1)	return false;
	for(int i = 2; i*i<=n; i++){
		if(0==n%i)
			return false;
	}
	return true;
}
void DFS(int n, int *vis, int *A, int cur, int &K, int &OK){
	if(cur==n && isp[ A[0]+A[cur-1]]){//不要漏掉1和最后一个的和是否为素数
		//OK = 1;//没有奇偶判断时用来标记是否有素数环存在
		for(int i=0; i<n; i++)
			printf("%d ",A[i]);
		printf("\n");
	}
	for(int i=2; i<=n; i++){
		if(!vis[i] && isp[i+A[cur-1]]){
			vis[i]=1;
			A[cur]=i;
			DFS(n, vis, A, cur+1, K, OK);
			vis[i]=0;
		}

	}


}

int main(){
	for(int i = 0; i < 2*N; i++ )
		isp[i] = is_prime(i);
	/*这里可以用另一种素数筛选法————找那些不是素数的数,不是素数则标记为1	
//在这里可以尝试其他的素数筛选法	
			for(int i = 2; i < 10; i++)
			if(!isp[i])
			for(int j = 2*i; j < 50; j += i)
			isp[j] = 1;
			*/
	int n, K=0;
	while(~scanf("%d", &n)&&n){
		int vis[N], A[N], cur, OK;
		printf("Case %d:\n", ++K);
		memset(vis, 0, sizeof(vis)); memset(A, 0 , sizeof(A));//memset函数的第二个参数要注意是int 型还是 char 型,第三个参数应该是///实际的长度
		vis[1]=1;  A[0]=1; cur =1; OK = 0;
		if(1 == n) {
			printf("1\n");
			continue;
		}
		if(0 !=  n%2){ //在这里有一个常识,也是做这个题时间方面要考虑的:只有奇数和偶数个数相等时才能形成素数环,如果不相等的话,势必有两个奇//数在一起这样和就不是素数,所以只有偶数个才形成素数环(1除外,应为2是特殊的素数)。没有这个优化,在NYOJ运行会超时
			printf("No Answer\n");
			continue;
		}

		DFS(n, vis, A, cur, K, OK);
		/*if(!OK){
			printf("No Answer\n");
		}*/
	}
	return 0;
}
/*在这里进行了一下素数的测试,怕自己出错
   int main(){
   for(int i = 0; i < 2*N; i++){
   isp[i] = is_prime(i);
   printf("isp[%d]=%d  ",i, isp[i]);
   }
   return 0;
   }
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值