1、刚开始用筛法求素数先弄出素数表,再判断回文,果断超空间了。。。
2、后来看了官网的HINT,写了8个生成回文的程序。。。
3、但是不得不说,官网题解的程序真漂亮,真简洁啊。。。而且判断素数的函数也比我写得好。。。学习了!
/*
ID:mrxy564
PROG:pprime
LANG:C++
*/
#include<cstdio>
#include<string>
#include<cmath>
#include<cstring>
using namespace std;
int ans[1000010];
int cnt=0;
bool is_prime(int n){
int m=(int)sqrt(n+0.5);
for(int i=2;i<=m;i++){
if(n%i==0) return false;
}
return true;
}
void gen_0(){
for(int i=5;i<=9;i++){
if(is_prime(i))
ans[cnt++]=i;
}
}
void gen_1(){
int num;
for(int i=1;i<=9;i+=2){
num=i*11;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_2(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++){
num=i*101+j*10;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_3(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++){
num=i*1001+j*110;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_4(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++){
num=i*10001+j*1010+k*100;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_5(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++){
num=i*100001+j*10010+k*1100;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_6(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
for(int h=0;h<=9;h++){
num=i*1000001+j*100010+k*10100+h*1000;
if(is_prime(num))
ans[cnt++]=num;
}
}
void gen_7(){
int num;
for(int i=1;i<=9;i+=2)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
for(int h=0;h<=9;h++){
num=i*10000001+j*1000010+k*100100+h*1100;
if(is_prime(num))
ans[cnt++]=num;
}
}
int main(){
freopen("pprime.in","r",stdin);
freopen("pprime.out","w",stdout);
int i,a,b;
scanf("%d%d",&a,&b);
gen_0();gen_1();gen_2();gen_3();
gen_4();gen_5();gen_6();gen_7();
for(int i=0;i<cnt;i++)
if(ans[i]>=a&&ans[i]<=b) printf("%d\n",ans[i]);
else if(ans[i]>b) break;
return 0;
}
官方题解:
The main problem here is that we need some way to generate palindromes. Since there are only about 10,000 palindromes less than 100,000,000, we can just test each one to see if it is prime and in the range.
To generate a palindrome, we start with the first half and reverse it. The trick is that we can repeat the middle character or not repeat the middle character. I call a palindrome with a repeated middle character "even" (because it is of even length) and one without "odd". So from the string "123", we can generate the even palindrome "123321" or the odd palindrome "12321".
We can generate all palindromes by doing the following:
- length 1: generate odd palindromes using 1..9
- length 2: generate even palindromes using 1..9
- length 3: generate odd palindromes using 10..99
- length 4: generate even palindromes using 10..99
- ...
The "generate" function does exactly this, using "genoddeven" to first generate the odd palindromes for a range and then the even ones.
The "gen" function generates an even or odd palindrome for a number by converting it to a string, making a palindrome, and converting the resulting string back to a number. Then it tests to see if the number is in the range and prime. If so, it is printed.
We could speed this up in a number of ways: use a faster primality test, don't generate palindromes past "b", etc. But this is already plenty fast, and doing such things makes the program more complex and might introduce bugs.
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
FILE *fout;
long a, b;
int
isprime(long n)
{
long i;
if(n == 2)
return 1;
if(n%2 == 0)
return 0;
for(i=3; i*i <= n; i+=2)
if(n%i == 0)
return 0;
return 1;
}
void
gen(int i, int isodd)
{
char buf[30];
char *p, *q;
long n;
sprintf(buf, "%d", i);
p = buf+strlen(buf);
q = p - isodd;
while(q > buf)
*p++ = *--q;
*p = '\0';
n = atol(buf);
if(a <= n && n <= b && isprime(n))
fprintf(fout, "%ld\n", n);
}
void
genoddeven(int lo, int hi)
{
int i;
for(i=lo; i<=hi; i++)
gen(i, 1);
for(i=lo; i<=hi; i++)
gen(i, 0);
}
void
generate(void)
{
genoddeven(1, 9);
genoddeven(10, 99);
genoddeven(100, 999);
genoddeven(1000, 9999);
}
void
main(void)
{
FILE *fin;
fin = fopen("pprime.in", "r");
fout = fopen("pprime.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%ld %ld", &a, &b);
generate();
exit (0);
}
master_zed writes:
The problem can be simplified slightly by noticing that any even palindrome is divisible by 11. Therefore, 11 is the ONLY even prime palindrome. This eliminates the need to deal with 2 cases:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
FILE *fout;
long a, b;
int
isprime(long n)
{
long i;
if(n == 2)
return 1;
if(n%2 == 0)
return 0;
for(i=3; i*i <= n; i+=2)
if(n%i == 0)
return 0;
return 1;
}
void
gen(int i)
{
char buf[30];
char *p, *q;
long n;
sprintf(buf, "%d", i);
p = buf+strlen(buf);
q = p - 1;
while(q > buf)
*p++ = *--q;
*p = '\0';
n = atol(buf);
if(a <= n && n <= b && isprime(n))
fprintf(fout, "%ld\n", n);
}
void
generate(void)
{
int i;
for (i = 1; i <= 9; i++)
gen(i);
if(a <= 11 && 11 <= b)
fprintf(fout, "11\n");
for (i = 10; i <= 9999; i++)
gen(i);
}
void
main(void)
{
FILE *fin;
fin = fopen("pprime.in", "r");
fout = fopen("pprime.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%ld %ld", &a, &b);
generate();
exit (0);
}
Coach Rob writes:
I guess I have a slightly different coding style than the previous two solutions. This is the same idea but coded a bit more tightly (thanks to Michael Coblenz for its kernel):
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int primelist[100000];
int nprimes;
int isPrime(int num);
int reverse2(int i, int j);
int compare(const void *p, const void *q) { return *(int *)p-*(int *)q; }
void main (void) {
ifstream infile("pprime.in");
ofstream outfile("pprime.out");
int i, j, begin, end, num;
infile>>begin>>end;
if (begin <= 11 && 11 <=end)
primelist[nprimes++] = 11;
for (j = 0; j <= 999; j++)
for (i = 0; i <= 9; i++) {
num = reverse2(j,i);
if (num >= begin && num <=end && isPrime(num))
primelist[nprimes++] = num;
}
qsort(primelist, nprimes, sizeof(int), compare);
for (i = 0; i < nprimes; i++)
outfile << primelist[i] << "\n";
}
int
reverse2(int num, int middle) {
int i, save=num, digit, combino = 1;
for (i = 0; num; num /= 10) {
digit = num % 10;
i = 10 * i + digit;
combino *= 10;
}
return i+10*combino*save+combino*middle;
}
int isPrime(int num) {
int i;
if (num <= 3) return 1;
if (num%2 == 0 || num%3 ==0) return 0;
for (i = 5; i*i <= num; i++)
if (num %i ==0)
return 0;
return 1;
}
And here is another tightly coded solution from Anton Titov:
I guess you may find intresting my solution to Prime Palindromes as I use a function to generate palindromes, that is purely arythmetical it does not use strings, sprintf, reversion or other things. It uses recursion, but my guess is that it will outpreform all other functions listed.
Function void genPalind(int num, int add, int mulleft, int mulright)
expects 4 parameters, first is the number (N) of digits you want for your palindromes, second should be 0 for direct calls, third should be 10^(N-1) for direct calls and last one should be 1 for direct calls.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
FILE *f;
int a, b;
int isPrime(int num);
void genPalind(int num, int add, int mulleft, int mulright);
void tryPalind(int num);
int main(){
int i;
char first;
f=fopen("pprime.in", "r");
fscanf(f, "%d%d", &a, &b);
fclose(f);
f=fopen("pprime.out", "w");
if (a<=5)
fprintf(f, "%i\n", 5);
if (a<=7 && b>=7)
fprintf(f, "%i\n", 7);
if (a<=11 && b>=11)
fprintf(f, "%i\n", 11);
genPalind(3, 0, 100, 1);
genPalind(5, 0, 10000, 1);
genPalind(7, 0, 1000000, 1);
fclose(f);
}
void tryPalind(int num){
if (!(num&1))
return;
if (num<a || num>b)
return;
if (!(num%3) || !(num%5) || !(num%7))
return;
if (!isPrime(num))
return;
fprintf(f, "%d\n", num);
}
void genPalind(int num, int add, int mulleft, int mulright){
int i, nmulleft, nmulright;
if (num==2){
for (i=0; i<10; i++)
tryPalind(add+mulleft*i+mulright*i);
}
else if (num==1){
for (i=0; i<10; i++)
tryPalind(add+mulright*i);
}
else {
nmulleft=mulleft/10;
nmulright=mulright*10;
num-=2;
for (i=0; i<10; i++)
genPalind(num, add+i*mulleft+i*mulright, nmulleft, nmulright);
}
}
int isPrime(int num){
int koren, i;
koren=(int)sqrt(1.0*num);
for (i=11; i<=koren; i+=2)
if (!(num%i))
return 0;
return 1;
}
本文介绍了使用筛法求素数并判断回文的过程,优化了生成回文素数的程序,展示了简洁高效的代码实现,并提供了多种生成回文素数的方法。

4353

被折叠的 条评论
为什么被折叠?



