C语言:素数筛法与分解素因数
2018-01-30 23:35
302 查看
一、素数筛法
素数筛法是关于求小于某个大数(正整数)的所有素数的算法,首先有理论:任何整数n≥2都可以分解成若干质数的乘积,即n=p1p2···pr。
用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列,
1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。如有:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
1不是素数,去掉(编者注:可以直接从2开始)。剩下的数中2最小,是素数,去掉2的倍数,余下的数是:
3 5 7 9 11 13 15 17 19 21 23 25 27 29
剩下的数中3最小,是素数,去掉3的倍数,如此下去直到所有的数都被筛完,求出的素数为:
2 3 5 7 11 13 17 19 23 29(摘自百度百科~~)
用算法描述为:
二、分解素因数(一道研究生上机试题)
题目描述:
求正整数N(N>1)的质因数的个数。
相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
输入:
可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。
输出:
对于每组数据,输出N的质因数的个数。
样例输入:
样例输出:
提示:
注意:1不是N的质因数;若N为质数,N是N的质因数。
思路分析:
求N的质因数个数,可以按2,3,4,5.,6..这样去试探是否能够整除(比如最开始试探2,则N会一直整除2,直至不能除尽,因此不用担心后面的序列4,6等会被计为素数),需要注意的是,如果将试探上限设置到N,会导致超时,将试探上线设置为“sqrt(N)+1”即可,因为对N的质因数序列,至多只能包含一个大于sqrt(N)的因数(若有2个,则二者之积必大于N,矛盾)。
另一思路:利用前面素数筛法求出的素数,可以减小试探域,只用prime数组中的素数去试探,该算法其实是做了前期工作,在整体上比上面的思路的实效好好写,尤其是在输出大数时更明显。
素数筛法是关于求小于某个大数(正整数)的所有素数的算法,首先有理论:任何整数n≥2都可以分解成若干质数的乘积,即n=p1p2···pr。
用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列,
1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。如有:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
1不是素数,去掉(编者注:可以直接从2开始)。剩下的数中2最小,是素数,去掉2的倍数,余下的数是:
3 5 7 9 11 13 15 17 19 21 23 25 27 29
剩下的数中3最小,是素数,去掉3的倍数,如此下去直到所有的数都被筛完,求出的素数为:
2 3 5 7 11 13 17 19 23 29(摘自百度百科~~)
用算法描述为:
int prime[100000]; //存放素数 int mark[100000]; //标记脚标表示的数字是否是素数 int prime_size; //素数的个数 void init() {//素数筛选函数 prime_size =0; for (int i = 0; i < 100000; i++) //标记数组初始化 mark[i]=false; for (int i = 2; i < 100000; i++) { if(mark[i]==true) continue; //若是素数则跳过 else //非素数 { prime[prime_size++] = i; //将该素数存入数组 for (int j = i; j < 100000; j+=i) //标记该素数的倍数为非素数 mark[j]=true; } } }在主函数中调用init()函数,就可以较为迅速的将1~100000之间的所有素数保存于数组prime中,prime_size记录的是素数的个数
二、分解素因数(一道研究生上机试题)
题目描述:
求正整数N(N>1)的质因数的个数。
相同的质因数需要重复计算。如120=2*2*2*3*5,共有5个质因数。
输入:
可能有多组测试数据,每组测试数据的输入是一个正整数N,(1<N<10^9)。
输出:
对于每组数据,输出N的质因数的个数。
样例输入:
120
样例输出:
5
提示:
注意:1不是N的质因数;若N为质数,N是N的质因数。
思路分析:
求N的质因数个数,可以按2,3,4,5.,6..这样去试探是否能够整除(比如最开始试探2,则N会一直整除2,直至不能除尽,因此不用担心后面的序列4,6等会被计为素数),需要注意的是,如果将试探上限设置到N,会导致超时,将试探上线设置为“sqrt(N)+1”即可,因为对N的质因数序列,至多只能包含一个大于sqrt(N)的因数(若有2个,则二者之积必大于N,矛盾)。
int main() { int n; int factor_size; int sqrnum,inputnum; while (scanf("%d",&n)!=EOF) { factor_size=0; sqrnum = (int)sqrt(double(n)); int i =2; while (n>1) { if (n%i==0) //i为n的素因数 { factor_size++; n/=factor_size; } else { i++; if (i>sqrnum) { factor_size++; break; } } } printf("%d\n",factor_size); }return 0; }
另一思路:利用前面素数筛法求出的素数,可以减小试探域,只用prime数组中的素数去试探,该算法其实是做了前期工作,在整体上比上面的思路的实效好好写,尤其是在输出大数时更明显。
int main() { int n; init(); int factor_size; int factor[50]; int factor_value[50]; int sqrnum,inputnum; while (scanf("%d",&n)!=EOF) { factor_size=0; inputnum = n; sqrnum = (int)sqrt(double(n))+1; for (int i = 0; i < 50; i++) factor[i]=0; for (int i = 0; i < prime_size&& prime[i]<sqrnum; i++) { if(n%prime[i]==0) { while (n%prime[i]==0) //当prime[i]为n的因数时 { factor[factor_size]++; factor_value[factor_size]=prime[i]; n/=prime[i]; } factor_size++; if(n==1) break; //n被除至1,退出循环 } } if(n>1) //n仍未被分解至1,则剩余的因数一定是大于100000的素因数,其值就是现在的n { factor[factor_size]++; factor_value[factor_size++]=n; } int ans=0; for (int i = 0; i < factor_size; i++) ans += factor[i]; printf("%d\n",ans); } return 0; }黑框运行结果:
相关文章推荐
- 百炼-2749-分解因数-C语言-递归算法
- c语言的字符串分解——strtok函数和strsep函数
- 批量分解素因数(二)
- 复试训练——数学问题—— 分解素因数
- C语言编程问题:因式分解 参数返回问题
- HDU-1492(素因数分解_easy)
- c语言的字符串分解——strtok函数和strsep函数
- 批量分解素因数(一)
- 分解素因数
- 【源代码】将一个整数的每位数分解并按逆序放入一个数组中(用递归算法)(C语言实现)
- 算数基本定理——素因数分解序列生成
- c语言--简单素数筛法
- 对称矩阵的LDLT分解(C语言)
- poj2407Relatives(欧拉公式,素因数分解)
- UVA - 10699 - Count the factors(分解素因数)
- C语言分解三位数
- 机试算法讲解:第26题 分解素因数
- Hdu 1395 2^x mod n = 1 (欧拉定理 分解素因数)
- c语言的字符串分解——strtok函数和strsep函数
- c语言:将一个正整数分解质因数