我有一个C代码,在下面找到大的完美数字,
#include <stdio.h>
int main ()
{
unsigned long long num,i,sum;
while (scanf ("%llu",&num) != EOF && num)
{
sum = 1;
for (i=2; i*i<=num; i++)
{
if (num % i == 0)
{
if (i*i == num)
sum += i;
else
sum += (i + num/i);
}
}
if (sum == num)
printf ("Perfect\n");
else if (sum > num)
printf ("Abundant\n");
else
printf ("Deficient\n");
}
return 0;
}
我试图找出一个数字是完美的,丰富的还是不足的。我运行循环到num
的平方根以最小化运行时。它工作正常<= 10^15
但是对于较大的值,执行时间太长。
例如,对于以下输入集,
8
6
18
1000000
1000000000000000
0
此代码显示以下输出
Deficient
Perfect
Abundant
Abundant
Abundant
但是,对于10 ^ 16,它没有快速响应。
那么,有没有更好的方法来找到太长时间值的完美数字?或者有更好的算法在这里实现??? :)
答案 0 :(得分:2)
是的,有更好的算法。
你的算法基本上就是一个简单的算法 - 将一个数的除数加起来找到一个数的除数之和(不包括它自己)。但是你可以使用数论公式来找出一个数的除数之和(包括它自身)。如果除n
的素数为p1
,p2
,...,pk
以及n
的规范分解中的素数的幂数为{ {1}},a1
,...,a2
,然后ak
的除数之和为
n
您可以比找到所有 (p1**(a1+1) - 1) / (p1 - 1) * (p2**(a2+1) - 1) / (p2 - 1) * ...
* (pk**(ak+1) - 1) / (pk - 1)
的除数更快地找到素数除数及其指数。从上面的表达式中减去n
,你得到你想要的总和。
当然,有一些技巧可以更有效地找到n
和pi
:我会把它留给你。
顺便说一下,如果您的目的只是为了找到完美的数字,就像在标题中一样,那么您最好使用Euclid's formula for even prime numbers。通过检查素数ai
的所有2**p-1
来查找梅森素数,看它们是否为素数 - 这样做也有捷径 - 然后从梅森素数构造一个完美的数字。但是,这会遗漏任何odd perfect numbers。如果您发现任何问题,请让数学界知道 - 这会让您闻名于世。
当然,找到完美数字的最快方法是使用其中一些数字的the lists already made。
答案 1 :(得分:1)
这是数字因素化的问题。您可以在此处阅读更多内容:https://en.wikipedia.org/wiki/Integer_factorization
不幸的是,没有好消息 - 数字越大,需要的时间越长。
要从代码开始,请尽量不要在每次迭代时乘以i*i
。
代替:
for(i = 2; i * i&lt; = num; i ++)
首先计算num的平方根,然后进行比较
i <= square_root_of_num in the loop
。
答案 2 :(得分:1)
// Program to determine whether perfect or not
# include <bits/stdc++.h>
using namespace std;
map<long long int, int> mp; // to store prime factors and there frequency
void primeFactors(long long int n)
{
// counting the number of 2s that divide n
while (n%2 == 0)
{
mp[2] = mp[2]+1;
n = n/2;
}
long long int root = sqrt(n);
// n must be odd at this point. So we can skip every even numbers next
for (long long int i = 3; i <= root; i = i+2)
{
// While i divides n, count frequency of i prime factor and divide n
while (n%i == 0)
{
mp[i] = mp[i]+1;
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
{
mp[n] = mp[n]+1;
}
}
long long int pow(long long int base, long long int exp)
{
long long int result = 1;
base = base;
while (exp>0)
{
if (exp & 1)
result = (result*base);
exp >>= 1;
base = (base*base);
}
return result;
}
int main ()
{
long long num, p, a, sum;
while (scanf ("%lld",&num) != EOF && num)
{
primeFactors(num);
sum = 1;
map<long long int, int> :: iterator i;
for(i=mp.begin(); i!=mp.end(); i++)
{
p = i->first;
a = i->second;
sum = sum*((pow(p,a+1)-1)/(p-1));
}
if (sum == 2*num)
printf ("Perfect\n");
else if (sum > num)
printf ("Abundant\n");
else
printf ("Deficient\n");
mp.clear();
}
return 0;
}