zoukankan      html  css  js  c++  java
  • 大范围内高效查找回文质数(回文数猜想)

    人们认为,回文数中存在无穷多个素数11,101,131,151,191……。除了11以外,所有回文素数的位数都是奇数。道理很简单:如果一个回文素数的位数是偶数,则它的奇数位上的数字和与偶数位上的数字和必然相等;根据数的整除性理论,容易判断这样的数肯定能被11整除,所以它就不可能是素数。
    最初几个回文素数:11,101,131,151,181,191,313,353,373,383,727,757,787,797,919,929……两位回文素数1个,三位回文素数15个,五位回文素数93个,七位回文素数668个,九位回文素数5172个。

    /*题目描述
    因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数。
    写一个程序来找出范围[a,b](5 <= a < b <= 100,000,000)( 一亿)间的所有回文质数;
    输入输出格式
    输入格式:
    第 1 行: 二个整数 a 和 b .
    输出格式:
    输出一个回文质数的列表,一行一个。

    输入样例:
    5 500
    输出样例:
    5
    7
    11
    101
    131
    151
    181
    191
    313
    353
    373
    383
    */

    思路:先定义两个判断函数,一个用于判断一个整数M是否为质数(is_ prime),一个用于判断一个整数M是否为回文数(is_hws)
    按照下面的程序块去执行样例(5 99999999)总耗时:9.134秒,还算可以,没有超时。
    这里写图片描述
    做个测试!交换一下两个判断函数的位置后(即先判断素数在判断回文数)再去执行样例(5 99999999)总耗时:38.854秒
    分析原因,可能是花在判断质数的时间太长了!
    这里写图片描述

    #include<bits/stdc++.h>
    using namespace std;
    
    int is_hws(int num)
    {
        int m=num,sum=0;
        while (m)
        {
            sum = sum*10 + m%10;
                m /= 10;
        }
        if (sum == num)
            return 1;
        else
            return 0;
    }
    
    int is_prime(int s)
    {
        if(s==0||s==1)
        {
            return 0;
        }
        if(s==2)
        {
            return 1;
        }
        for(int i=2; i*i<=s; i++)
        {
            if(s%i==0)
            {
                return 0;
            }
        }
        return 1;
    }
    
    int ws(int k)  //位数
    {
        if(k>=10 && k<100 && k!=11 || k>=1000 && k<10000)return 0;
        if(k>=100000 && k<1000000 || k>=10000000 && k<100000000)return 0;
        return 1;
    }
    /*
    之所以先找回文数(并依据尾数筛选掉那些不符的)再在回文数中找素数
    是因为那样的回文数比素数数量要少
    */
    int main()
    {
        long long a,b;
        cin>>a>>b;
        if(b>10000000) b/=10;
        for(int i=a;i<=b;i++)
        {
            if(ws(i)&&is_hws(i))
            {
                if(is_prime(i))
                    cout<<i<<endl;
            }
        }
        return 0;
    }

    那么,还有没有别的什么方法来进一步优化呢
    思考一下!如果回文数用循环生成,这样就不用判断回文数了~

    说明
    提示 1: 找出所有的回文数再判断它们是不是质数(素数).
    提示 2: 要产生正确的回文数,你可能需要几个像下面这样的循环。

    eg.产生长度为5的回文数:

    for (d1 = 1; d1 <= 9; d1+=2) { // 只有奇数才会是素数
         for (d2 = 0; d2 <= 9; d2++) {
             for (d3 = 0; d3 <= 9; d3++) {
               palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;//(处理回文数...)
             }
         }
     }

    1)1位回文质数只有5,7;2位回文质数只有11。因此此部分可以直接打表。
    2)可以证明不存在4,6,8位(以及更大偶数位)的回文质数,因此此部分可以忽略。
    3)按照题目要求的范围,9位数最多只有100000000一个数,而且不是回文质数,因此此部分可以忽略。
    4)注意每一个打表或构造得到的回文数,要判断是否在闭区间[m,n]内。小于m就continue,大于n就return 0(因为此后所有数一定都大于n)。
    5)每个经过上述四步得到的回文数,输出并换行即可。

    #include<bits/stdc++.h>
    using namespace std;
    bool ispr(int n)
    {
        for(int k=2;k<=sqrt(n);++k)
        if(n%k==0)
        return false;
        return true;
    }
    int getsize(int n)
    {
        int m=1,k=n;
        while(k>9)
        {
            k/=10;
            ++m;
        }
        return m;
    }
    int main()
    {
        int l,m,n,q,w,i,j,k;
        cin>>m>>n;
        q=getsize(m);
        w=getsize(n);
        if(q<=1&&w>=1)
        {
            if((m<=5)&&(n>=5))
            cout<<5<<endl;
            if((m<=7)&&(n>=7))
            cout<<7<<endl;
        }
        if((q<=2)&&(w>=2))
        {
            if((m<=11)&&(n>=11))
            cout<<11<<endl;
        }
        if((q<=3)&&(w>=3))
        {
            for(int a=1;a<=9;a+=2)
            for(int b=0;b<=9;++b)
            {
                int f=a*100+b*10+a;
                if(f<m)
                continue;
                if(f>n)
                return 0;
                if(ispr(f))
                cout<<f<<endl;
            }
        }
        if((q<=5)&&(w>=5))
        {
            for(int a=1;a<=9;a+=2)
            for(int b=0;b<=9;++b)
            for(int c=0;c<=9;++c)
            {
                int f=a*10000+b*1000+c*100+b*10+a;
                if(f<m)
                continue;
                if(f>n)
                return 0;
                if(ispr(f))
                cout<<f<<endl;
            }
        }
        if((q<=7)&&(w>=7))
        {
            for(int a=1;a<=9;a+=2)
            for(int b=0;b<=9;++b)
            for(int c=0;c<=9;++c)
            for(int d=0;d<=9;++d)
            {
                int f=a*1000000+b*100000+c*10000+d*1000+c*100+b*10+a;
                if(f<m)
                continue;
                if(f>n)
                return 0;
                if(ispr(f))
                cout<<f<<endl;
            }
        }
        return 0;
    }

    这里写图片描述




    【附:一文一图】
    这里写图片描述

  • 相关阅读:
    PHP调试总结
    vim常用命令
    Xshell
    JavaScript
    HTML+CSS
    解决VMware“该虚拟机似乎正在使用中”问题
    MVC dirname(——FILE——)
    各种编程语言中的指针和引用
    Go defer 原理和源码剖析
    软件架构定义的流派
  • 原文地址:https://www.cnblogs.com/zhouie/p/8955805.html
Copyright © 2011-2022 走看看