Prime Palindromes( 素数回文) C++实现
2010-04-15 18:49
316 查看
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
前面的算法实现运行完总共需要的时间要好几分钟,结果还没运行完。这个时间上的差距确实很大很大。这里仅仅做了一个小小的优化而已。
其实这里还有很大的提高空间。
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
前面的算法实现运行完总共需要的时间要好几分钟,结果还没运行完。这个时间上的差距确实很大很大。这里仅仅做了一个小小的优化而已。
其实这里还有很大的提高空间。
相关文章推荐
- USACO-section1.5 Prime Palindromes[回文数][素数]
- USACO Section 1.5 Prime Palindromes(回文数+素数)
- 素数回文——输出两整数之间所有既是回文数又是素数的数 C++实现
- 洛谷P1217 [USACO1.5]回文质数 Prime Palindromes
- USACO1.5]回文质数 Prime Palindromes
- C++实现素数的求法
- 打印1-100之间的素数 C++实现
- luogu P1217 [USACO1.5]回文质数 Prime Palindromes
- USACO-Prime Palindromes(部分筛法判素数,回文数生成)
- C++第七次实验-素数和回文
- USACO1.5 回文质数 Prime Palindromes
- 获取小于N的素数 优化筛选法的C++实现
- C/C++ Prime学习要点1——实现memcpy库函数
- 第11周项目6输出1-1000的所有素数、回文数、回文素数、可逆素数(调用三个函数实现输出目标数)
- C++第7次实验-项目一:素数与回文
- USACO 1.5 prime Palindromes 回文质数(vector的使用)
- 洛谷 P1217 回文质数 Prime Palindromes(递归)
- C++第7次实验-项目1:素数和回文
- C++第七次实验——素数和回文
- C++实现Miller-Rabin素数测试