回文数多还是质数多,谈USACO回文质数题Prime Palindromes

2014-11-24 01:41:33 · 作者: · 浏览: 1
题意是求出a到b的回文质数,b最大可为1亿。
先判断是回文数还是质数是很有意思的!如果是1亿,则用得到前一半,反转它,得到后一半,让两者结合在一起的方法的话,那么可以通过1到1万,得到1亿以内的所有回文数。例如9876,反转后是6789,拼在一起,得到98766789。看看三位数有多少个回文数。
三位数的回文数都是aba的形式,a可以为1到9,b可以为0到9,则有90个。四位数的回文数为abba的形式,ab可以为10到99,则有90个。一亿以内的回文数,假如0不算的话,那么最小的为1,最大的为9999 9999,即为1位数到8位数的所有回文数,记为s。
现要求n位数的回文数个数,f(n)=9*10^[(n-1)/2],则显然s=f(n),(n=1,2,……,8).s=9+9+……9000+9000。s=2*(9+90+900+9000)=2*(10000-1)=19998。
那有大约有多少个质数呢?
根据素数定理,a以内的质数个数约为a/ln(a)。1亿/ln(1亿)约为5428681。
可见质数远多于回文数!
实际情况如何?用isPrime(i)&&palindrome(i)作为判断语句的话,输出1亿以内的全部回文质数,要35秒,而用palindrome(i)&&isPrime(i),只用19秒!而把palindrome(i),isPrime(i)先计算保存起来,再判断的话,要54秒。
有趣的是,打表的时候发现,除了11,没有偶位数的回文质数!采用直接构造回文数再判断是否为质数的方法更快,而且只用构造奇数位的回文数,像这样求出所有构造所有n位数的回文数:
void getPali(int n)  
{  
        int len=n/2+1;  
        int minN=getMin(len);  
        char s[12];  
        for(int i=minN;i=len;j--)  
                s[j]=s[2*len-2-j];  
            s[2*len-1]='\0';  
            int ans;  
            sscanf(s,"%d",&ans);  
            if(ans>b) return;  
            else if(ans 
  

这样就能AC这题了!
完整代码为:
/* 
{ 
ID: lzwjava1 
PROG: pprime 
LANG: 
C++
} */ #include #include #include #include #include #include using namespace std; const int maxn=10000; bool vis[maxn]; int prime[1300]; int pn; void get_prime()//素数表 { memset(vis,false,sizeof(vis)); pn=0; for(int i=2;i=len;j--) s[j]=s[2*len-2-j]; s[2*len-1]='\0'; int ans; sscanf(s,"%d",&ans); if(ans>b) return; else if(ans