我在编码网站上尝试了一个代码来找到一个数字的最大素数因子,并且它超过了最后一个测试用例的时间限制,可能他们使用的是一个大的素数。能帮我降低以下代码的复杂性吗?
int main()
{
long n;
long int lar, fact;
long int sqroot;
int flag;
cin >> n;
lar=2, fact=2;
sqroot = sqrt(n);
flag = 0;
while(n>1)
{
if((fact > sqroot) && (flag == 0)) //Checking only upto Square Root
{
cout << n << endl;
break;
}
if(n%fact == 0)
{
flag = 1;
lar = fact;
while(n%fact == 0)
n = n/fact;
}
fact++;
}
if(flag == 1) //Don't display if loop fact reached squareroot value
cout << lar << endl;
}
此处我还负责循环检查,直到Square Root值。不过,我怎样才能进一步降低其复杂性?
答案 0 :(得分:1)
您可以通过提供用于初始值fact
的前N个素数的硬编码列表来加快速度(如果不降低复杂性),因为使用fact
的复合值是浪费时间。之后,避免明显的fact
复合值(如偶数)。
答案 1 :(得分:1)
您可以通过跳过大于2的偶数来减少测试次数,如果找到较小的因子,则可以更快地停止测试。这是一个更简单,更快速的版本:
int main() {
unsigned long long n, lar, fact, sqroot;
cin >> n;
lar = 0;
while (n && n % 2 == 0) {
lar = 2;
n /= 2;
}
fact = 3;
sqroot = sqrt(n);
while (fact <= sqroot) {
if (n % fact == 0) {
lar = fact;
do { n /= fact; } while (n % fact == 0);
sqroot = sqrt(n);
}
fact += 2;
}
if (lar < n)
lar = n;
cout << lar << endl;
return 0;
}
我不确定输入数字可能变得多大,使用较大类型unsigned long long
进行这些计算会比long
更远。使用预先计算的素数数组会有所帮助,但不是很大的因素。
答案 2 :(得分:1)
我获得的更好的结果是使用下面的函数(lpf5()
)。它基于primality()
函数(下面)使用公式6k + 1,6k-1来个别化素数。所有素数&gt; = 5可以以p=k*6+1
或p=k*6-1
中的一种形式表示,其中k> 0(但不是具有这种形式的所有数字都是素数)。开发这些公式我们可以看到如下序列:
k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...
5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...
我们观察到术语之间的差异是2和4.这样的结果也可以使用简单的数学来获得。很明显,k * 6 + 1和k * 6-1之间的差异是2.很容易注意到k * 6 + 1和(k + 1)* 6-1之间的差异是4。
当x为素数(或0 - 小心)时,函数primality(x)
返回x,当x不是素数时,第一个除数发生。
我认为您可以在primality()
函数中获得更好的结果lpf5()
函数。
我还尝试在素数函数中插入一个带有一些素数的表(从1到383 - 所示公式的前128个结果中的素数),但速度差异是不可靠的。
这里是代码:
#include <stdio.h>
#include <math.h>
typedef long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);
uint64 lpf5(uint64 x)
{
uint64 x_=x;
while ( (x_=primality(x))!=x)
x=x/x_;
return x;
}
uint64 primality(uint64 x)
{
uint64 div=7,f=2,q;
if (x<4 || x==5)
return x;
if (!(x&1))
return 2;
if (!(x%3))
return 3;
if (!(x%5))
return 5;
q=sqrt(x);
while(div<=q) {
if (!(x%div)) {
return div;
}
f=6-f;
div+=f;
}
return x;
}
int main(void) {
uint64 x,k;
do {
printf("Input long int: ");
if (scanf("%llu",&x)<1)
break;
printf("Largest Prime Factor: %llu\n",lpf5(x));
} while(x!=0);
return 0;
}