超级素数

定义m(m>1)位超级素数:

  1. m位超级素数本身为素数
  2. 从高位开始,去掉1位后为m-1位素数、去掉2位后为m-2位素数、…… 、去掉m-1位后为1位素数

例如137是一个3位数的超级素数,因为137是一个3位素数、去掉高1位后得37是一个2位素数、去掉高2位得7是一个1位素数,而素数107不是超级素数,因为去掉高1位得7不是一个2位素数;

输入整数m(1< m<=10),统计m位超级素数的个数,并输出其中最大的m位超级素数;

试应用枚举与递推两种算法设计求解;


枚举设计

1.说明:

(1)、为了方便判别素数,应用试商法设计素数判别函数p(k):若k为素数,p(k)返回1;否则,p(k)返回0

(2)、为枚举m位数需要,通过自乘10(即c=c*10)计算m位数的起始数c;

(3)、设置枚举m位奇数的f循环:

  • 若f不是素数或f的个位数字不是3或7(超级素数的个位数字必然是3或7),则返回;

  • 若f的其他各位数字出现“0”,显然应予排除;

  • 除m位数f本身及其个位数已检验外,从高位开始去掉1位,2位,……,m-2位可得m-2个数(f%k,k=100,1000,……,10*m-1),这m-2个数的p函数值相乘为t:若t=0,说明m-2个数中至少有一个非素数,则返回;若t=1,说明m-2个数全为素数,应用变量作统计个数

  • 为输出最大的m位超级素数,在统计的同时进行赋值:e=f,最后输出的e则为最大的m位超级素数;

2.程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   int i,m;
   long c,d,e,f,k,s,t;
   int p(long f);
   printf("请确定m(m>1):");
   scanf("%d",&m);
   for(c=1,i=1;i<=m-1;i++)  /*确定最小的m位数c*/
      c=c*10;
   s=0;
   for(f=c+1;f<=10*c-1;f=f+2)  /*设置枚举循环,f为m位奇数*/
   {
      if(!(f%10==3||f%10==7)||p(f)==0)
         continue;
      for(t=1,d=f/10,i=1;i<=m-2;i++)
      {
         if(d%10==0)  /*如果包含0数字,标记t=0*/
         {
            t=0;
            break;
         }
         d=d/10;
      }
      if(t==0)
         continue;
      for(k=10,i=1;i<=m-2;i++)  /*枚举m-2次去位操作*/
      {
         k=k*10;
         if(p(f%k)==0)  /*若其中任一数不是素数则退出循环*/
            break;
      }
      if(i>m-2)
      {
         s++;        /*统计*/
         e=f;        /*赋值*/
      }
   }
   printf("共%ld个%d位超级素数。\n",s,m);
   printf("其中最大数为%ld。\n",e);
}
int p(long k)  /*设计素数检测函数*/
{
   int j,h,z=0;
   if(k==2)
      z=1;
   if(k>=3&&k%2==1)
   {
      for(h=0,j=3;j<=sqrt(k);j+=2)
         if(k%j==0)
         {
            h=1;
            break;
         }
      if(h==0)   /*k为素数返回1,否则返回0*/
         z=1;
   }
   return z;
}

3.程序运行示例及其注意事项:

请确定m(m>1):5
共192个5位超级素数。
其中最大数为99643。

注意:所得5位超级素数99643从高位“去位”后所得9643、643、43、3分别为4、3、2、1位素数,所以超级素数各位数上不可能存在0


递推设计

1.说明:

根据超级素数的定义,m位超级素数去掉高位数字后是m-1位超级素数。一般地,k(k=2,3,……,m)位超级素数去掉高位数字后是k-1位超级素数;

那么,在已求得g个k-1位超级素数 a[i](i=1,2,……,g)时,在 a[i] 的高位加上一个数字j(j=1,2,……,9),得到9*g个k位候选数 f=j *e[k]+a[i](e[k]=10^(k-1)),只要对这个 9 *g个k位候选数检测即可,这就是从k-1递推到k的递推关系;

注意到超级m(m>1)位素数的个位数字必然是3或7,则得递推的初始(边界)条件:

  • a[1]=3,a[2]=7,g=2

2.程序设计:

#include<stdio.h>
#include<math.h>
int main()
{
   int g,i,j,k,m,t,s;
   double d,f,a[20000],b[20000],e[20];
   int p(double f);
   printf("请确定m(m>1):");
   scanf("%d",&m);
   g=2;
   s=0;
   a[1]=3;   /*递推的初始条件*/
   a[2]=7;
   e[1]=1;
   for(k=2;k<=m;k++)
   {
      e[k]=e[k-1]*10;
      t=0;
      for(j=1;j<=9;j++)
         for(i=1;i<=g;i++)
         {
            f=j*e[k]+a[i];  /*产生9*g个候选数f*/
            if(p(f)==1)
            {
               t++;
               b[t]=f;
               if(k==m)  /*统计并记录最大的超级素数*/
               {
                  s++;
                  d=f;
               }
            }
         }
      g=t;
      for(i=1;i<=g;i++)  /*g个k位b[i]赋值给a[i]*/
         a[i]=b[i];
   }
   printf("共%d个%d位超级素数。\n",s,m);
   printf("其中最大数为%.0f。\n",d);
}
int p(double k)
{
   int h,z=0;
   double j;
   long t;
   t=(int)pow(k,0.5);
   for(h=0,j=3;j<=t;j+=2)
      if(fmod(k,j)==0)
      {
         h=1;
         break;
      }
   if(h==0)  /*k为素数返回1,否则返回0*/
      z=1;
   return z;
}

3.程序运行示例及其注意事项:

请确定m(m>1):9
共545个9位超级素数。
其中最大数为999962683。

两个算法时间复杂度比较

应用枚举设计:需要对m位奇数进行检测,枚举数量级为10^m;

应用递推设计:只需要检测9*g(k-1)个(g(k-1)为k-1位超级素数的个数),k=2,3,……,m,因而求m位超级素数共检测的次数为:

s(m)=9*(m-1)∑(k=1)g(k)

这里s(m)是对递推设计的时间复杂度的定量估算,其数量级远低于10^m,即递推设计的时间复杂度要低于枚举设计;

例如,当m=5时,应用枚举设计,需要调用检测函数p(k)次数为23697;而应用递推设计调用p(k)函数次数仅为9*(2+11+39+99)=1359;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值