素数中的素数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
质数中的质数
给定整数N(2<N<8),生成所有其前任意位都是质数的N位质数。
7331即是一个这样的4位质数,因为7、73和733也均为质数。
在标准输出上按升序输出所有符合要求的质数。
例如,对于2,输出下列9个数:
23 29 31 37 53 59 71 73 79
问题分析:首先此问题归结到底还是求素数的问题。
求素数的问题是最基本的程序之一。
而此问题需要解决的是如何求一个数的前面的那些位数是否是素数的问题。
我们可以按整除运算,再利用循环解决此问题。
1、输入所需要进行运算的位数num
2、调用函数fun(),此函数命名按标识符命名规则命名
3、fun()函数将解决此问题。
fun()函数的思想是利用循环,从2*10^num+1开始,到10^(num+1)结束。
取这个循环中这个数的首位,进行判断,是否为4、6、8,如果是则加上10^num,再进行后面的循环。
因为,4、6、8不是素数,所以排除以这些数为首位的数。
循
环变量每次加2,因为素数除2外都是奇数。
4、调用yprime(i,num),判断数i是否为所求的数。
判断原数是否为素数,再依次去掉后面的数,看是否为素数。
最后如果全部满足,则返回1,否则返回0;
5、判断素数,调用函数prime(n)。
程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void fun(int num);
int yprime(int n,int num);
int prime(int n);//n是否是素数
int main()
{
int num=0;
printf("请输入位数:");
scanf("%d",&num);
fun(num);
return 0;
}
//从后面往前面数,每位是否是素数
//如7331,733,73,7都是素数
//输出位数num以内的所有满足这一条件的数
void fun(int num)
{
int i,t,n=1;
for(i=1; i<num; i++)
n*=10;
for (i=2*n+1; i<n*10; i+=2)//首位为1的数也不满足条件
{
t=i/n;
if(t==4 ||t==6 || t==8)//首位为4、6、8的数不满足条件
i+=n;
if(yprime(i,num))//输出满足条件的数
printf("%d\t",i);
}
}
//满足条件,则返回1,不满足条件,返回0
int yprime(int n,int num)
{
int i;
for(i=0; i<num; i++)
{
if(!prime(n))
return 0;
n/=10;
}
return 1;
}
int prime(int n)//n是否是素数
{
int a=sqrt(n),i;
for(i=2; i<=a; i++)
if(n%i==0) return 0;
return 1;
}
在Microsoft Windows XP SP3(1.20GHz,988MB)上运行Code::Blocks 10.05,得运行结果如下:
请输入位数:2
23 29 31 37 53 59 71 73 79
Process returned 0 (0x0) execution time : 0.266 s
Press any key to continue.
请输入位数:3
233 239 293 311 313 317 373 379 593 599 719 733 739 797
Process returned 0 (0x0) execution time : 0.219 s
Press any key to continue.
请输入位数:4
2333 2339 2393 2399 2939 3119 3137 3733 3739 3793 3797 5939 7193 7331 7333 7393
Process returned 0 (0x0) execution time : 0.219 s
Press any key to continue.
请输入位数:5
23333 23339 23399 23993 29399 31193 31379 37337 37339 37397
59393 59399 71933 73331 73939
Process returned 0 (0x0) execution time : 0.719 s
Press any key to continue.
请输入位数:6
233993 239933 293999 373379 373393 593933 593993 719333 739391 739393 739397 739399
Process returned 0 (0x0) execution time : 1.094 s
Press any key to continue.
请输入位数:7
2339933 2399333 2939999 3733799 5939333 7393913 7393931 7393933
Process returned 0 (0x0) execution time : 9.875 s
Press any key to continue.
请输入位数:8
23399339 29399999 37337999 59393339 73939133
Process returned 0 (0x0) execution time : 237.484 s
Press any key to continue.
当输入2、3、4、5时,由于输入较慢,而程序运行比较快,所以产生了现在的这个时间。
由此结果分析可知,当输入位数为8时,程序运行的时间有点长,因此,我们想到改进算法。
在函数yprime(i,num)中是直接进去调用的,是否可以加一个函数来判断一下,这个数字除首位外是否含有偶数,如果有则不进行调用运算,进行归一处理(即比此数的大,又能够进行处理的最小的一个整数)。
举个例子:2999,当得到一个这样的数的时候,我们要对齐进行归一处理,加上112得到3111,这个数是比2999大的一个数,又能够进行后面的去处的一个数,且是这些数中的最小的一个。
进行归一处理的方法是,当求模时出现9的个数,那么相应的加上这么多位的1,再加上1,得到比刚刚的那个数大的最小的能够进行处理的数。
另外一种描述方式:是不是对于循环的数,进行一下优化,每次加的时候,要么加2,要么加20……。
这样我们可以得到一种改进的算法:
对循环进行改进:
m=df=dm=1;
for(j=1; j<num; j++)
{
m*=10;
df*=m;
dm*=10;
dm-=1;
if(i%m==dm)
{
i+=df/10+1;
if(yprime(i,num))//输出满足条件的数
printf("%d\t",i);
}
}
此复合语句实现的也就是:每次加的时候,要么加2,要么加20……。
在进行归一
处理的时候,对9加2,对99加12,……,对9999999加1111112进行处理。
运行结果为:
请输入位数:8
23399339 29399999 37337999 59393339 73939133 Process returned 0 (0x0) execution time : 238.375 s
Press any key to continue.
由结果分析,知此种改进,并没有带来时间上的减少。
相反,当位数增加的时候,由于循环里面的判断,使得原本可以改进的地方,现在却变成了负担。
因为是判断前面的位数是否为素数,我们可以采用利用之前得到的结果,进行乘10,再循环几次,就可以得到一些数。
如果前面的数都不是素数,那么后面再怎么加,也不会是满足题目所给条件的素数。
由以上结果分析知,满足这种条件的质数是很少的,基于此,我们采用迭代算法:void fun(int num)
{
int i;
for(i=2; i<10; i++)
{
if(prime(i))//对于是素数的数才进行调用
dis(i,num-1,num);
}
}
void dis(int n,int m,int num)
{
int i;
if(m==0)//结束调用的标志
{
if(yprime(n,num-m))//满足所有的条件,就输出
printf("%d\t",n);
return;
}
n*=10;
for(i=1; i<10; i+=2)//对数位上为奇数的数进行循环
{
if(yprime(n+i,num-m))
dis(n+i,m-1,num);//对满足条件的数进行迭代运算
}
}
运行结果为:
请输入位数:4
2333 2339 2393 2399 2939 3119 3137 3733 3739
3793 797 5939 7193 7331 7333 7393
Process returned 0 (0x0) execution time : 0.422 s
Press any key to continue.
请输入位数:5
23333 23339 23399 23993 29399 31193 31379 37337 37339
37397 59393 59399 71933 73331 73939
Process returned 0 (0x0) execution time : 0.328 s
Press any key to continue.
请输入位数:6
233993 239933 293999 373379 373393 593933 593993 719333 739391
739393 739397 739399
Process returned 0 (0x0) execution time : 0.313 s
Press any key to continue.
请输入位数:7
2339933 2399333 2939999 3733799 5939333 7393913 7393931 7393933
Process returned 0 (0x0) execution time : 0.469 s
Press any key to continue.
请输入位数:8
23399339 29399999 37337999 59393339 73939133
Process returned 0 (0x0) execution time : 0.406 s
Press any key to continue.
请输入位数:9
Process returned 0 (0x0) execution time : 0.516 s
Press any key to continue.
对于结果的分析,让我们大吃一惊。
原来用三分钟的时间,现在用时不到1秒,还由于手动输入的原因,所以实际运行时间比这还短。
由此,我们还计算得到,9位数是不存在这个数的。
而此算法是由后面往前面进行调用的,是否可以由前面往后面进行调用,从而减少运算次数。
这样也可以很大的提高运算速度,节约时间。
此想法和上面的迭代算法有类似之处,在此不做过多分析。
对结果进行分析,我们也可以得到这样一条信息,除首位出现2和5,其它地方都是1、3、7、9这三个数字。
所以,能不能想出一种只利用这三个数字的组合来求这一质数呢?。