分解质因数
前言
数学苦手来计算 1+1 的答案了,以下内容可能引起某些dalao的不适或血压升高,建议快速跳过,纯当乐子。
疑问
对于任何一个数N,其因子可以两两配对,我们枚举小因子。易知小因子 >=sqrt(N),大因子 >=sqrt(N),因此考虑从 2 到 sqrt(N) 枚举小因子。同时应该考虑大因子,因为并不是所有质因子都 <=sqrt(N) 的!
但是网上的试除法是这样说的:
扫描 2 到 sqrt(N) 中的每个数,如果 x 能整除 N,从 N 中除掉所有质因子 x
这样扫描出来的x确实全部都是质数,但是并没有考虑大因子,因此我觉得这是有问题的(显然是因为我太弱了~_~|||)
比如 17*2*2*3=204,sqrt(204)=14.2828568570587
考虑什么样的大因子不会被枚举到。首先这个大因子应该 >=sqrt(N),也就是说没有比它更大的质因子了,而且这样没有被枚举到的大质因子只能有一个。
根据这个,似乎可以改进我的算法:
v[ ] 为质数表 is[ ]为合数标记
原算法 divide1 需要遍历到 N 的最大质因子
inline void divide1(int x) { if(!is[x]) { printf("%d",x); return; } int pos=1; while(x!=1) { if(x%v[pos]==0) { while(x%v[pos]==0) { printf("%d ",v[pos]); x/=v[pos]; } } ++pos; } }
现算法 divide2 需要遍历到 min(floor(sqrt(N)),N的最大质因数))
inline void divide2(int x) { if(!is[x]) { printf("%d",x); return; } int pos=1; int li=sqrt(x); while(x!=1&&v[pos]<=li) { if(x%v[pos]==0) { while(x%v[pos]==0) { printf("%d ",v[pos]); x/=v[pos]; } } ++pos; } if(x!=1) { printf("%d ",x); } }
结果
运行时间对比
分解99999
算法1:0.0010000
算法2:0.0000000
分解30840
算法1:0.0030000
算法2:0.0010000
可见对于部分特殊数据,优化还是有用的。
结语
加快了自己分解质因数的时间效率,已经为之后学习更优的算法提供了动力。
题外话
我知道这种东西谁都会。所以请包容弱小的我。