P1217 [USACO1.5]回文质数 Prime Palindromes ※※※※※

mac2024-11-11  15

方法一: 先找出所有的素数 然后判断是不是回文数 这样做,会TLE

#include<stdio.h> #include<math.h> #include<string.h> int isp(int n) //判断素数 { if (n <= 1) return 0; int m = sqrt(n); for (int i = 2; i <= m; i++) { if (n % i == 0) return 0; } return 1; } int ism(int n) //判断回文 { char buf[20]; sprintf(buf, "%d", n); int len = strlen(buf); for (int i = 0; i <= len / 2 - 1; i++) { if (buf[i] != buf[len - i - 1]) return 0; } return 1; } int ap[1000000]; int main() { memset(ap, 0, sizeof(ap)); int a, b; scanf("%d%d", &a, &b); int j = 0; for (int i = a; i <= b; i++) //找到所有的素数 { if (isp(i)) ap[j++] = i; } for (int k = 0; k < j; k++) //判断是不是回文数 { if (ism(ap[k])) printf("%d\n", ap[k]); } return 0; }

方法二: 找到所有的回文数 判断是不是素数

#include<stdio.h> #include<math.h> #include<string.h> int sum1 = 0; int sum = 0; int a, b; int isp(int n)//判断是不是素数 { if (n <= 1) return 0; int m = sqrt(n); for (int i = 2; i <= m; i++) { if (n % i == 0) return 0; } return 1; } //比如,131,那么我就选择1和3。而后面的1则是利用回文性质生成的 void make_m_ji(int k) //选择奇位数据 { if (k != 0) for (int d = 0; d <= 9; d++) //此乃选择 { sum = sum * 10 + d; make_m_ji(k - 1); //dfs吧?选择下一位 sum = (sum - d) / 10; } else //这是代表选择完毕,要生成回文数据 { char buf[15]; sprintf(buf, "%d", sum); //把13存入字符串 int n = strlen(buf); int i = 0; while (i < n && n - i - 2 >= 0) //利用回文性质,以及字符串的特性,生成回文 { buf[n + i] = buf[n - i - 2]; i++; } buf[i + n] = '\0'; sscanf(buf, "%d", &sum1); //这样把生成的回文数存入sum1中 if (sum1 <= b && sum1 >= a && isp(sum1)) //判断sum1是不是素数 printf("%d\n", sum1); } return; } void make_m_ou(int k) //其实偶位数据生成不必添加的,但是因为我事先不知道,所以还是增添了 { //代码和奇位数据生成是一样的,只不过对于偶位回文生成的时候,做了一点小改动 if (k != 0) for (int d = 0; d <= 9; d++) { sum = sum * 10 + d; make_m_ou(k - 1); sum = (sum - d) / 10; } else { char buf[15]; sprintf(buf, "%d", sum); int n = strlen(buf); int i = 0; while (i < n && n - i - 1 >= 0) { buf[n + i] = buf[n - i - 1]; //改了这里!! i++; } buf[i + n] = '\0'; sscanf(buf, "%d", &sum1); if (sum1 <= b && sum1 >= a&&isp(sum1)) printf("%d\n", sum1); } return; } int main() { scanf("%d%d", &a, &b); int count = 0; int b1 = b; while (b1 != 0) { b1 /= 10; count++; } //判断最大一共有多少位 for (int i = 1; i <= count; i++) //从最低位生成到最高位 { for (int d1 = 1; d1 <= 9; d1 += 2) { sum = d1; /*比方说:如果i==3,那么我就是要生成3位的数据,那么我就选择好前两位的数,第3位则与第1位相同,利用回文性质直接生成 如果i==4,那么我就是要生成4位数据,那么我依然选择前两位的,第3、4位则与第2、1位相同,利用回文性质生成即可*/ if (i % 2) //i是代表数据有几位。 make_m_ji((i - 1) / 2); else make_m_ou((i - 2) / 2); /*if (i == 1&& sum >= a && sum <= b&&isp(sum)) printf("%d\n", sum);*/ //如果加上这句,那么会对5,7进行打印重复两遍。而导致这个情况产生的原因,是因为我修改了is_m_ji()函数。 sum -= d1; //为下一次选择做准备,也就是dfs中的返回 } } return 0; }

总结

基本上也就是一种递归的实现形式。 还是老样子,深度优先搜索,dfs

形式如此:

void dfs(int step) { 判断边界 尝试每一种可能 for (i = 1; i <= n; i++) { 继续下一步 dfs(step + 1); } 返回 }

此题的思想与P1026一样 我都是用了这种方法,定要再多看几次!

然后,下面是别人的题解。牛逼的题解!!!

打表法

打表法就是将题目中需要的答案集合提前算出来,存到代码里,根据题目所需取答案,这种方法通常只需要将程序挂着,在表打完后进行加工,最终取答案程序时间复杂度为O(1),空间复杂度为O(n)(n为答案规模); 当数据规模过大,打表不仅慢,而且内存会爆。

回文数的判定方法

bool pd_h(int x) { int y = x, num = 0; //下面的,就是把x倒过来,再与x比较 while (y != 0) { num = num * 10 + y % 10; //将上一次数字的记录进位再加上下一位的 y /= 10; } if (num == x) return 1; else return 0; }

埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。 在筛质数时,我们会发现,筛去2后,2的倍数4、6、8等一定不是素数;筛去3后,3的倍数6、9、12等一定不是倍数。

// 用埃氏筛法生成质数表 void prime(int b) { //初始化,默认全部都是质数 memset(book, true, sizeof(book)); book[1] = false;//1不是质数 int n = sqrt(b); for (int i = 2; i <= n; i++) { if (book[i]) { //质数的倍数绝对不是质数,把所有质数的倍数全部设为false for (int j = 2; j <= b / i; j++) book[i * j] = false; // i*j<=b } } } 时间复杂度O(n*lglgn)
最新回复(0)