Prime Palindromes( 素數迴文) C++實現
Prime Palindromes
Time limit: 15sec. Submitted: 10679
Memory limit: 32M Accepted: 1958
Source: USACO Gateway
The number 151 is a prime palindrome because it is both a prime number and a palindrome (it is the same number when read forward as backward). Write a program that finds all prime palindromes in the range of two supplied numbers a and b (5 <= a < b <= 1000,000,000); both a and b are considered to be within the range .
Input
Line 1: Two integers, a and b
Output
The list of palindromic primes in numerical order, one per line.
Sample Input
5 500
Sample Output
5
7
11
101
131
151
181
191
313
353
373
383
開始拿到題目的時候,一看。恩!挺簡單的,於是邊嘩啦啦地開始coding。
很快,程式碼寫好了。
首先我們先判斷以下一個數是不是素數,這個就暫時想到樸素素數法了。
bool is_primer(const unsigned int number)
28 {
29 int i;
30 unsigned int sqrt_num;
31 sqrt_num = sqrt(number + 1);
32 for(i = 3; i <= sqrt_num; i += 2)
33 {
34 if((number % i) == 0)
35 return false;
36 }
37 return true;
38 }
接下來就是該寫palindromele了, 自己也沒有多考慮,就是按正常的方法直接把函式寫完,如下所示:
bool is_palindrome(const unsigned int number)
41 {
42 int button , top, middle;
43 unsigned int temp = number;
44 button = top = 0;
45 int i = 0;
46 int array[11];
47 while(1)
48 {
49 array[i] = temp % 10;
50 temp = temp /10;
51 if(temp == 0)
52 break;
53 i++;
54 }
55 top = i;
56 if(top % 2 != 0)
57 {
58 if(number == 11)
59 return true;
60
61 return false;
62 }
63 middle = top/2;
64 for(i = 0; (i <= middle)&& (top >= button); i++)
65 {
66 if(array[button] == array[top])
67 {
68 button++;
69 top--;
70 }
71 else
72 return false;
73 }
74 return true;
75 }
int main(void)
8 {
9 unsigned int min_bounder, max_bounder;
10 cin >> min_bounder >> max_bounder;
11
12 unsigned int i;
13
14 for(i = min_bounder; i < max_bounder; i++)
15 {
16 if((i % 2) != 0)
17 {
18 if(is_primer(i)&& is_palindrome(i))
19 {
20 cout << i << endl;
21 }
22 }
23 }
24
25 }
哈哈,大功告成! 等等....還沒有Submit呢! 提交一看,慘了Time Limit Exceed!
到這一步,終於知道了,程式沒有自己想象中的那麼簡單。
考慮了一下,我們知道,迴文的判斷應該比素數的判斷要快,而且要比素數判斷簡單。所以應該先判斷完了是不是迴文,再判斷
其是否為素數,這樣速度回大有提高。於是改變一下回文判斷與素數判斷的先後順序。
if( is_palindrome(i)&&is_primer(i))
提交,結果還是超時!
這回好像的想想辦法了。可能是素數的判斷演算法效率太低了,還有可能是迴文的判斷效率低。於是我先來看看回文判斷有沒有可以提高的地方
想像一下1000,000,000。 這麼大的數, 如果是按照上面的辦法直接找回文的話。
迴圈for(i = min_bounder; i < max_bounder; i++)一遍就得 1000,000,000趟。可想而知,暫且不討論素數判斷問題,光是這個判斷就
足以超時了。
再仔細深入研究了一下, 我們可能會很容易發現1000,000,000的迴文最大為 999,999,999
而此處,由於是迴文。我們只需要前半部分就可以了,所以我們可以把迴圈縮小為10000就可以了,比如說
1230321這個數,我們僅僅需要得到前面的半部分123就行了。
想到這裡,演算法也就已經出來了。同時我們還應該注意到一個問題,這個問題也可已很快地提高程式執行的速度
那就是偶數偶數位迴文都不是素數,舉個例子吧:
1551 可以被11整除, 153351也可以被11整除, 同理, 偶數位的迴文都可以被11整除。
於是程式又可以得到了進一步的簡化, 執行速度上也可以得到了很大的提高。
把迴文函式修改一下如下所示:
#include <iostream>
#include <cmath>
using namespace std;
bool is_primer(const unsigned int number);
bool is_palindrome(const unsigned int min_bound, const unsigned int max_bound);
int power(const int a, const int n);
int reverse_num(const int number , unsigned int &total, int &reverse);
int main(void)
{
unsigned int min_bounder, max_bounder;
cin >> min_bounder >> max_bounder;
is_palindrome(min_bounder, max_bounder);
return 0;
}
/*判斷是否為素數*/
bool is_primer(const unsigned int number)
{
int i;
int sqrt_num;
sqrt_num = sqrt(number);
for(i = 3; i <= sqrt_num; i += 2)
{
if((number % i) == 0)
return false;
}
return true;
}
/*獲取迴文的函式*/
bool is_palindrome(const unsigned int min_bound, const unsigned int max_bound)
{
int array[] = {5 , 7, 11};
int log_n_max = log(max_bound)/log(10);
int log_n_min = log(min_bound)/log(10);
int reverse = 0;
log_n_max /= 2;
log_n_min /= 2;
int middle_max = power(10, log_n_max);
int middle_min = power(10, (log_n_min-1));
unsigned int result = 0 , temp = 0;
if(min_bound <= 11 )
{
for( int i = 0 ; i < 3 ; ++i )
{
if( min_bound <= (unsigned)array[i] )
{
cout << array[i] << endl ;
}
}
}
int i , j , n = 0;
for(i = middle_min; i < middle_max; i++)
{
n = reverse_num(i, result, reverse);
temp = result;
if(reverse % 2 != 0)
{
/*這裡我們只考慮奇數位數的迴文, 這個迴圈實現如 12 將得到 12021 12121.....12921 */
for(j = 0; j < 10; j++)
{
temp = temp*10 + j*power(10, n);
temp = temp + reverse;
if(temp >= min_bound && temp < max_bound)
{
if(is_primer(temp))
{
cout << temp <<endl;
}
}
else
continue;
temp = result;
}
}
}
return true;
}
/*a 的 n 次冪*/
int power(const int a, const int n)
{
unsigned int temp = 1;
int i = 0;
for(i =0; i < n; i++)
{
temp *= a;
}
return temp;
}
/*把 number reverse 一下, 如123 --> 321 */
int reverse_num(const int number , unsigned int &total, int &reverse)
{
int temp = number , result = 0;
int array;
total = number;
int i = 1;
while(1)
{
array = temp % 10;
temp /= 10;
result = result * 10 + array;
total *= 10;
if(temp == 0)
break;
i++;
}
reverse = result;
return i;
}
實現到這一步之後,可以進行提交了,submit一下,OK。成功了。這裡沒有使用更好的素數判斷演算法,也沒有這個必要了。15secs的時間足夠了,
提交時,剛剛好消耗了0.45s的時間。
Proid Subtime Judgestatus Runtime Memory Language Code Length
1004 2010-04-15 18:02:13 Accepted 0.45 s 1248 K C++ 2581 B
後來我有和之前的程式對比了以下執行5 1000 000 000
前面的演算法實現執行完總共需要的時間要好幾分鐘,結果還沒執行完。這個時間上的差距確實很大很大。這裡僅僅做了一個小小的優化而已。
其實這裡還有很大的提高空間。
相關文章
- 素數迴文——輸出兩整數之間所有既是迴文數又是素數的數 C++實現C++
- 1013 數素數 (20分)/c++實現C++
- Diff-prime Pairs(思維+素數篩)AI
- UVA 11584 Paritioning by Palindromes(動態規劃 迴文)動態規劃
- python技巧——使用list comprehension生成素數(prime number)Python
- C++ Prime 學習C++
- 迴圈佇列C++實現佇列C++
- 杭電OJ2029迴文串——Palindromes _easy version(C語言解析)C語言
- python 學習--使用filter來實現判斷迴文數PythonFilter
- 10月15日 棧和佇列實現迴文數字佇列
- PAT1013數素數C++C++
- 簡單的素數問題(C++)C++
- c++遞迴與迭代實現漢諾塔C++遞迴
- Python演算法實現質數(素數)判斷Python演算法
- 特殊迴文數(很坑
- java判斷迴文數Java
- ch2_8_3求解迴文序列問題(遞迴實現)遞迴
- c++實現求眾數及其重數C++
- ACM之判斷迴文數ACM
- 邱奇數的C++實現C++
- 任意進位制下的可逆素數 C++C++
- 使用 call/cc 實現計數迴圈
- LeetCode迴文數(Python)LeetCodePython
- C語言:迴文數計算C語言
- LeetCode9[迴文數]LeetCode
- C++ :引用計數(reference count) 實現C++
- 【資料結構】實現迴圈連結串列(c++)資料結構C++
- 【資料結構】迴圈佇列的實現(c++)資料結構佇列C++
- acm-(區間dp、迴文串、子序列)ICPC SG Preliminary Contest 2018 C - Making PalindromesACM
- 斐波那契數列的遞迴和非遞迴實現遞迴
- 迴文串問題(動態規劃DP C++)動態規劃C++
- LeetCode-N9-迴文數LeetCode
- java列印出迴文數格式方陣Java
- 可抹位迴文數方程式
- 藍橋杯之特殊迴文數JAVAJava
- ACM 素數ACM
- 對數機率迴歸(邏輯迴歸)原理與Python實現邏輯迴歸Python
- C++反射機制:可變引數模板實現C++反射C++反射