给定一个数,求一个新数要大于等于这个数,而这个新数既要是palindromes回文又要是prime素数。
题目很简单,有人都使用取巧的方法保存好结果直接查表。
或者暴力法求解。
这里不使用保存表的方法,也不要用暴力法。- 这些方法都不好。
使用的技巧有:
1 而是使用next palindrome的技巧,只需要O(n),n是数位,可以认为是常数了。
2 判断素数的方法,时间效率是O(sqrt(n)), n是数值大小,如果是重复判断很多数是否是素数是有办法优化的,但是如果是单个素数判断的话,我还想不到,也找不到优化的方法。
不过怎么都好,下面程序假设它是需要重复判断数是素数的,那么就可以保持一个数组的方法,然后只需要判断这个数是否能被这个数组中小于这个数n的sqrt(n)除尽,就可以快速判断出这个数是否是素数了。
当然本题好像直接判断是否是素数就可以了。
原题:http://www.codechef.com/problems/PRPALIN/
全部实现上面的优化,那么程序还是非常繁琐的,也是出于学习的目的吧。
#include <assert.h> #include <string> #include <stdio.h> #include <math.h> #include <iostream> using namespace std; namespace{ static const int MAX_NUM = 1100; } bool allNines(string a) { bool nines = true; for (int i = 0; i < (int)a.size() && nines; i++) { if (a[i] != ‘9‘) nines = false; } return nines; } string nextPalindrome(string a) { if (allNines(a)) { a[0] = ‘1‘; for (int i = 1; i < (int)a.size(); i++) { a[i] = ‘0‘; } a.push_back(‘1‘); return a; } int mid = (a.size() >> 1); int L = mid - 1, R = mid + 1; if (a.size() % 2 == 0) R--;//确定中心 int i = L, j = R;//查找不同点下标 for ( ; i >= 0 && j < (int)a.size() && a[i] == a[j]; i--, j++); bool leftsmall = false; if (i < 0 || a[i] <= a[j]) leftsmall = true;//i<0排除了等于的情况了 for ( ; i >= 0; i--, j++) { a[j] = a[i]; } if (leftsmall) { int carry = 1; if (a.size() % 2) { a[mid]++; if (a[mid] > ‘9‘) a[mid] = ‘0‘; else carry = 0; } i = L, j = R; while (carry) { a[i]++; if (a[i] > ‘9‘) a[i] = ‘0‘; else carry = 0; a[j] = a[i]; i--, j++; } } return a; } bool isPalindrome(string s) { bool palin = true; for (int i = 0, j = int(s.size()) - 1; i < j; i++, j--) { if (s[i] != s[j]) palin = false; } return palin; } int PrimePalindromes() { bool primes[MAX_NUM+1] = {0}; for (int i = 2; i <= MAX_NUM; i++) { if (!primes[i]) { for (int j = (i<<1); j <= MAX_NUM; j += i) { primes[j] = true; } } } int primeNums[MAX_NUM] = {0}; int id = 0; for (int i = 2; i <= MAX_NUM; i++) { if (!primes[i]) primeNums[id++] = i; } string s; cin>>s; int sn = stoi(s); assert(1 <= sn && sn <= 1000000); if (!isPalindrome(s)) s = nextPalindrome(s); while (true) { sn = stoi(s); int sq = (int)sqrt((double)sn); bool isprimeNum = true; int i = 0; for ( ; primeNums[i] <= sq && i < id; i++) { if (sn % primeNums[i] == 0) { isprimeNum = false; break; } } if (isprimeNum) break; s = nextPalindrome(s); } cout<<s; return 0; }
codechef Prime Palindromes 题解
时间: 2024-10-28 10:53:47