• 洛谷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;
    }

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

  • 相关阅读:
    php文件下载方法收藏(附js下载技巧)
    微信自定义菜单类简单开发样例
    支付宝即时到账以及扫码支付相关注意事项
    ob系列函数归纳
    去除博客园底部图片广告的CSS代码
    TortoiseGit自动记住用户名密码的方法
    推荐分享一个牛X的自定义PHP加密解密类
    自动判断PC端、手机端跳往不同的域名JS实现代码
    unity 中 Tilemap的使用 笔记
    unity 判断平台(安卓,iOS还是编辑器)
  • 原文地址:https://www.cnblogs.com/horizonlc/p/10353610.html
Copyright © 2020-2023  润新知