洛谷P1217_回文质数(Prime Palindromes)

上学期作业题,但是当时打表近乎作弊,正好在洛谷上又遇到了,重做温习。

方法一:先利用筛法求出1~b的所有素数,存入到Prime数组中,再逐一判断是否为回文数

可是如果范围是1~100000000,则共有5761456个素数;

代码如下:

#include<iostream>
#include<fstream>
#include<cstring>
#include<ctime> 
using namespace std;
const int N=1E8;   //注意:1E8是浮点数,进行了强制类型转换
bool isPrime[N]={};
int Prime[6*1000000];

bool ifPalindrome(int n){
    int s[8]={}; 
    int cnt=0;
    while(n>0){
        s[cnt++]=n%10;
        n=n/10;
    }
    for(int i=0;i<cnt/2;i++){
        if(s[i]!=s[cnt-1-i]){
            return false;
        }
    }
    return true;
}
int main(){
    ofstream fout;
    fout.open("prime.txt");
    int a,b;
    cin >> a >> b;
    time_t begin,end;
    begin=clock();
    int cnt=0;
    for (int i = 2; i <= b; i++)
        isPrime[i] = true;
    for (int i = 2; i * i <= b; i++)
        if (isPrime[i])
            for (int j = i * i; j <= b; j += i)
                isPrime[j] = false;
    for (int i = 2; i <= b; i++)
        if (isPrime[i]){
            Prime[cnt++]=i;
     }
    for(int i=0;i<cnt;i++){
        if(Prime[i]>=a)
        if(ifPalindrome(Prime[i])){
            fout << Prime[i] << endl;
        }
    }
    end=clock();
    fout<<"runtime: "<<double(end-begin)<<endl; 
    fout.close();
    return 0;
     
}
///CLOCKS_PER_SEC

但是交上去以后发现第十个点总是TLE,遂通过<ctime>头文件获得当前时间从而相减获得程序运行时间(注意:此时间包括屏幕输出的时间,且单位为ms;可以除以1000(即常数CLOCKS_PER_SEC)以s为单位)

发现无论如何优化,该算法的特性限制了没有办法在1000ms内完成,一旦b的值较大(比如就是10^8时)无论abs(b-a)大小,所花时间都是2000+ms,因为此时筛法确实需要这么长的时间;

除去打表,也只能改变策略,不要先求1~b的全部素数再求回文数,而要先获得a~b的全部回文奇数(且个位非5)再判断是否为素数

方法二:先获得a~b的全部回文奇数,再判断是否为素数

1. 先求出100~100000000的全部回文奇数再找a~b范围内的?

2. 直接求出a~b之间的回文奇数?

3. 折中——求a,b的位数,找到该范围内的回文奇数  100~100000000之内的回文奇数总共才只有11100个

4. 判断是否为素数用什么方式?就用最原始的方式,每次判断的复杂度是O(n)

下面是AC代码:

#include<iostream>
#include<cstring>
#include<ctime>
#include<fstream>
using namespace std;
int palindrome[20000]={};   //100~100000000共有11100个回文奇数;
int cnt=0;
int digit(int n){
    int index=0;
    while(n>0){
        n=n/10;
        index++;
    }
    return index;
}

void create(int n){
    int d1,d2,d3,d4;
    switch(n){
        case 3:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    palindrome[cnt++]=d1*100+d2*10+d1;
            break;
        case 4:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    palindrome[cnt++]=d1*1000+d2*100+d2*10+d1;
            break;
        case 5:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    for(d3=0;d3<=9;d3++)
                        palindrome[cnt++]=d1*10000+d2*1000+d3*100+d2*10+d1;
            break;
        case 6:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    for(d3=0;d3<=9;d3++)
                        palindrome[cnt++]=d1*100000+d2*10000+d3*1000+d3*100+d2*10+d1;
            break;
        case 7:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    for(d3=0;d3<=9;d3++)
                        for(d4=0;d4<=9;d4++)
                            palindrome[cnt++]=d1*1000000+d2*100000+d3*10000+d4*1000+d3*100+d2*10+d1;
            break;
        case 8:
            for(d1=1;d1<=9;d1+=2)
                for(d2=0;d2<=9;d2++)
                    for(d3=0;d3<=9;d3++)
                        for(d4=0;d4<=9;d4++)
                            palindrome[cnt++]=d1*10000000+d2*1000000+d3*100000+d4*10000+d4*1000+d3*100+d2*10+d1;
            break;
    }
}

bool isPrime(int n){
    for(int i=2;i*i<=n;i++){
        if(n%i==0)
            return false;
    }
    return true;
}
int main(){
    int a,b;
    cin >> a >> b;
//    time_t begin,end;
//    begin=clock();
    int da=digit(a),db=digit(b);
    if(db<=8)
        for(int i=da;i<=db;i++){
            create(i);
        }
    else if(db==9)
        for(int i=da;i<=8;i++){
            create(i);
        }
    cout << cnt << endl;      
    if(a>11)    
        for(int i=0;i<cnt;i++){
            if(palindrome[i]>=a&&palindrome[i]<=b)
            if(isPrime(palindrome[i]))
                cout << palindrome[i] << endl;
            else if(palindrome[i]>b)
                break;
        }
    else{
        switch(a){
            case 1: case 2: cout << 2 << endl << 3 << endl << 5 << endl << 7 << endl << 11 << endl;  break;
            case 3: cout << 3 << endl << 5 << endl << 7 << endl << 11 << endl;  break;
            case 4: case 5: cout << 5 << endl << 7 << endl << 11 << endl;  break;
            case 6: case 7: cout << 7 << endl << 11 << endl;  break;
            case 8: case 9: case 10: case 11: cout << 11 << endl;  break;
        }
        for(int i=0;i<cnt;i++){
            if(palindrome[i]>=a&&palindrome[i]<=b)
            if(isPrime(palindrome[i]))
                cout << palindrome[i] << endl;
            else if(palindrome[i]>b)
                break; 
        }
    }
//    end=clock();
//    cout<<"runtime: "<<double(end-begin)/CLOCKS_PER_SEC<<endl;
    return 0;
}

关于两种算法的复杂度分析,等会再码字。

原文地址:https://www.cnblogs.com/horizonlc/p/10353610.html