素数对

本节探讨由两个满足某些特定条件的素数组成的素数对,包括经典的 孪生素数对逆序素数对


孪生素数对

相差为2的两个素数称为孪生素数对,简称孪生素数;

例如,3和5是一对孪生素数,41和43也是一对孪生素数;

试求出指定区间上的所有孪生素数对;

方案一 之 常规求解:

1.说明:

设置两个变量:当前素数变量i与相邻的前一个素数变量f,在求出当前素数i后,求i与它相邻的前一个素数f的差,如果i-f=2,则f和i为所求的一对孪生素数;

每求出一个素数i并作判断后,要注意把该素数i存储到f,为继续寻求孪生素数对做准备;

2.程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   long c,d,i,j,f=0;
   int t,n=0;
   printf("求区间[c,d]上的孪生素数对\n");
   printf("请输入c,d(c>2):");
   scanf("%ld,%ld",&c,&d);
   if(c%2==0)  /*确保起点c为奇数*/
      c++;
   for(i=c;i<=d;i+=2)
   {
      for(t=0,j=3;j<=sqrt(i);j+=2)  /*试商判别素数*/
         if(i%j==0)
         {
            t=1;
            break;
         }
      if(t==0)  /*t为0表明i为素数*/
      {
         if(i-f==2)
         {
            printf("(%ld,%ld)",f,i);
            n++;
         }
         f=i;  /*素数i存储到f,为后一判别做准备*/
      }
   }
   printf("\n[%ld,%ld]上共%d对孪生素数。\n",c,d,n);
}

3.程序运行示例:

求区间[c,d]上的孪生素数对
请输入c,d(c>2):2000,2100
(2027,2029)(2081,2083)(2087,2089)
[2001,2100]上共3对孪生素数。
方案二 之 设置数组求解:

1.说明:

应用试商法判定指定区间内的所有素数依次存储到a数组,a数组中相邻元素之差若为2,这两个素数相差为2,即为一对孪生素数;

2.程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   long c,d,i,j;
   int t,m,n=0;
   static long a[5000];
   printf("请输入c,d(c>2):");
   scanf("%ld,%ld",&c,&d);
   if(c%2==0)  /*确保起点c为奇数*/
      c++;
   for(m=0,i=c;i<=d;i+=2)
   {
      for(t=0,j=3;j<=sqrt(i);j+=2) /*试商法判别素数*/
         if(i%j==0)
         {
            t=1;
            break;
         }
      if(t==0)
         a[++m]=i; /*i为素数给a数组赋值*/
   }
   for(i=1;i<m;i++)
      if(a[i+1]-a[i]==2) /*相邻素数相差为2即输出*/
      {
         printf("(%ld,%ld)",a[i],a[i+1]);
         n++;
      }
   printf("\n[%ld,%ld]上共%d对孪生素数对。\n",c,d,n);
}

3.程序运行:

请输入c,d(c>2):1000,1100
(1019,1021)(1031,1033)(1049,1051)(1061,1063)(1091,1093)
[1001,1100]上共5对孪生素数对。

注意:
以上两种方法探求孪生素数对,在素数搜索上都是应用试商法,所不同的是:

  • 前者在每搜索到一个素数时立即判别是否为孪生素数对;

  • 后者则把区间上搜索到的所有素数存储在a数组中,再在a数组中从头到尾判定孪生素数对;


逆序素数对

逆序数对:由两个互为逆序数的不同整数组成逆序数对,例如15与51是2位逆序数对,107与701是3位逆序数对;

逆序素数对:如果逆序数对的两个整数都是素数,则称为逆序素数对(有些资料又称为回文素数对),例如13与31是2位逆序素数对,107与701是3位逆序素数对;

输入正整数n(1< n< 10),试统计并输出所有n位逆序素数对,为了避免重复,约定由素数d和r组成的逆序素数对(d,r)的较小数在前较大数在后,即d< r;

1.说明:

  • 应用试商法判别法把指定的n位整数中的所有素数(设共k个)存储在p数组,p[j]是这k个素数中升序排列的第j个(1<=j<=k);

  • 对于素数f=p[j],r=0赋初值,在i(1~n)循环中实施n次取整与取余运算:c=f%10;r=r*10+c;f=f/10;求得素数f=p[j]的逆序数r;

  • 设p[j]< r,注意到素数p[j]随j的增加而增加,为求逆序数r是否为素数,只要使r与所有大于p[j]的素数p[i](j+1<=i<=k)逐个比较:若未出现r=p[j],说明素数p[j]的逆序数r不是大于p[j]的素数,返回试下一个素数p[j];若出现r=p[i],即素数p[j]的逆序数r大于p[j]的素数p[i],则输出逆序素数对(p[j],r),并应用变量m统计逆序素数对的对数;

2.程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   long f,i,j,k,m,r,s,t,p[50000];
   int c,d,g,n;
   printf("请输入位数n(n>1):");
   scanf("%d",&n);
   k=s=0;
   t=1;
   for(j=1;j<=n-1;j++) /*计算最小的n位整数t*/
      t=t*10;
   for(m=t+1;m<=(10*t-1);m=m+2) /*枚举所有的n位奇数*/
   {
      if(m%5==0)
         continue;
      for(g=0,i=2;i<=sqrt(m);i++)
         if(m%i==0)
         {
            g=1;
            break;
         }
      if(g==0)
      {
         k++;
         p[k]=m;
      }
   }
   for(j=1;j<=k-1;j++)
   {
      f=p[j];
      c=f%10;
      d=f/t;
      if(c<d)  /*素数的逆序数比本身小的不考虑*/
         continue;
      for(r=0,i=1;i<=n;i++)
      {
         c=f%10;
         r=r*10+c;  /*r为d的逆序数*/
         f=f/10;
      }
      if(r<p[j])  /*素数的逆序数比本身小的不考虑*/
         continue;
      for(i=j+1;i<=k;i++)
         if(r==p[i])  /*逆序数r是比本身大的素数则输出*/
         {
            s++;
            printf("(%ld):%ld,%ld",s,p[j],r);
            if(s%5==0)
               printf("\n");
         }
   }
   printf("\n%d位逆序素数对共有%d对。\n",n,s);
}

3.程序运行示例及变通:

请输入位数n(n>1):3
(1):107,701(2):113,311(3):149,941(4):157,751(5):167,761
(6):179,971(7):199,991(8):337,733(9):347,743(10):359,953
(11):389,983(12):709,907(13):739,937(14):769,967
3位逆序素数对共有14对。

变通:试把程序中r与素数p[i](j+1<=i<=k)的比较循环修改为p[i](j<=i<=k),即素数p[j]的逆序数r也要与其本身p[j]比较,若有r=p[j],意味着素数p[j]的逆序数r就是其本身,此时素数p[j]即为对称素数

这一修改后,其输出自然包含了前面论述过的“对称素数”,例如输入n=3,则输出有29对,除了以上的14对逆序素数对之外,还加上15个3位对称素数;

顺便指出,网上有资料称Card经计算发现:“有13对3位回文素数对。”这一结论明显少了一对,应更正为14对;

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值