素数环(nyoj 488)

来源:互联网 发布:手机取色软件 编辑:程序博客网 时间:2024/04/29 14:13

素数环

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

有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环。

为了简便起见,我们规定每个素数环都从1开始。例如,下图就是6的一个素数环。

输入
有多组测试数据,每组输入一个n(0<n<20),n=0表示输入结束。
输出
每组第一行输出对应的Case序号,从1开始。
如果存在满足题意叙述的素数环,从小到大输出。
否则输出No Answer。
样例输入
6830
样例输出
Case 1:1 4 3 2 5 61 6 5 2 3 4Case 2:1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2Case 3:No Answer

这个题开始交了三四遍都是超时= =.改着改着居然又改成WA了.....

我觉得素数环有一个关键的地方在于 如果输入N是奇数的话,由于起点从1开始,那么1-N之间一共有N / 2个偶数,N / 2 +1个奇数,也就是奇数的个数比偶数多一个,那么把这N个数排成一个环,必然有两个奇数是相邻的,而两个奇数之和是偶数,偶数不是素数,所以我们得出结论,.这样当N是奇数的时候,直接输出no answer.  还有一点 1也是素数环.

做题的时候我还犯了一个错误....n虽然最大只有19, 但是,素数判断最大是19+18 = 37, 而我刚开始只把记录素数的数组开到了20....所以后面出错了,不太应该.

剩下的就是dfs了.因为第一个数是1,所以我在初始化数组的时候就把0位置置成1了,选数字的时候直接从2开始选就可以.

素数环有一个特点,那就是相邻两个数的奇偶性一定不同,因为奇数加上奇数等于偶数,偶数加上偶数也是偶数,而偶数一定不是素数,所有也可以在选取这一元素的时候跟上一元素比较下奇偶性,如果奇偶性相同,那么直接跳过.

#include<stdio.h>#include <string.h>#define SIZE 40int x;bool flag;bool prime [SIZE];bool vis[SIZE];int ans[SIZE];void isprime (){//素数筛选法 是素数置0 不是置1int i, j;prime[0] = prime[1] = 1;prime[2] = 0;for(i = 2; i * i <= SIZE; i++){if(!prime[i]){for(j = i + i; j <= SIZE; j += i){prime[j] = 1;}}}} void dfs(int cur){int i;if(cur == x && !prime[ans[cur - 1] + ans[0]]){//以为是环, 所以不要忘记判断第一个数和最后一个数相加是否也是素数flag = 1;for(i = 0; i < cur; i++){printf("%d ", ans[i]);}printf("\n");}else{for(i = 2; i <= x; i++){if(!vis[i] && !prime[ans[cur - 1] + i]){vis[i] = 1;ans[cur] = i;dfs(cur + 1);vis[i] = 0;}}}}int main (void){isprime();int n = 1;while (scanf("%d", &x)){if(x == 0)return 0;flag = 0;memset(vis, 0, sizeof(vis));memset(ans, 0, sizeof(ans));ans[0] = 1;printf("Case %d:\n", n++);if(x % 2 == 0 || x == 1)//如果是偶数或者是1才进行深搜,是奇数,直接no answerdfs(1);if(flag == 0){printf("No Answer\n");}}return 0;}






0 0
原创粉丝点击