Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Math 如何在C中找到高达10^18的完美数?_Math_Number Theory_Perfect Numbers - Fatal编程技术网

Math 如何在C中找到高达10^18的完美数?

Math 如何在C中找到高达10^18的完美数?,math,number-theory,perfect-numbers,Math,Number Theory,Perfect Numbers,我有一个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)

我有一个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;
}
此代码显示以下输出:

Deficient
Perfect
Abundant
Abundant
Abundant
但是,对于10^16,它的响应并不迅速


那么,对于太长的值,有没有更好的方法来找到一个完美的数字呢?或者这里有没有更好的算法可以实现??:)

是的,有一个更好的算法

你的算法基本上是简单的——把一个数的除数加起来,找到。。。一个数的除数之和(不包括它本身)。但是你可以用数论公式来求一个数(包括它本身)的除数之和。如果除数
n
p1
p2
,…,
pk
以及在
n
的规范分解中的这些素数的幂均
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
s和
ai
s:我将把它留给你


顺便说一句,如果你的目的只是为了找到完美的数字,比如你的标题,你最好使用。通过检查素数
p
的所有
2**p-1
来查找梅森素数,看看它们是否是素数——这也有捷径——然后从该梅森素数构造一个完美数。不过,这会省去任何一项。如果你发现了,让数学界知道——这会让你举世闻名


当然,找到完美数字的最快方法就是使用其中的一些。

是的,有一个更好的算法

你的算法基本上是简单的——把一个数的除数加起来,找到。。。一个数的除数之和(不包括它本身)。但是你可以用数论公式来求一个数(包括它本身)的除数之和。如果除以
n
的素数是
p1
p2
,…,
pk
,并且在
n
的规范分解中,这些素数的幂是
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
s和
ai
s:我将把它留给你


顺便说一句,如果你的目的只是为了找到完美的数字,比如你的标题,你最好使用。通过检查素数
p
的所有
2**p-1
来查找梅森素数,看看它们是否是素数——这也有捷径——然后从该梅森素数构造一个完美数。不过,这会省去任何一项。如果你发现了,让数学界知道——这会让你举世闻名


当然,找到完美数字的最快方法就是使用其中的一些。

这是数字的因式分解问题。您可以在此处阅读更多内容:

不幸的是,这对你来说不是什么好消息——数字越大,花费的时间就越长

从代码开始,尽量不要在每次迭代中乘以
i*i
。 而不是:
对于(i=2;i*i而言,这是数字的因式分解问题。您可以在此处阅读更多内容:

不幸的是,这对你来说不是什么好消息——数字越大,花费的时间就越长

从代码开始,尽量不要在每次迭代中乘以
i*i
。 而不是: 用于(i=2;i*i
//确定是否完美的程序
#包括
使用名称空间std;
map mp;//存储基本因子和频率
空隙系数(长整型n)
{
//计算除以n的2的数量
而(n%2==0)
{
mp[2]=mp[2]+1;
n=n/2;
}
长整数根=sqrt(n);
//n在这一点上一定是奇数,所以我们可以跳过所有偶数
用于(长整型i=3;i 2)
{
mp[n]=mp[n]+1;
}
}
长整型战力(长整型基地,长整型经验)
{
长整型结果=1;
基数=基数;
而(exp>0)
{
if(exp&1)
结果=(结果*基础);
exp>>=1;
基数=(基数*基数);
}
返回结果;
}
int main()
{
long-long-num,p,a,sum;
while(scanf(“%lld”,&num)!=EOF&&num)
{
原始因子(num);
总和=1;
迭代器i;
for(i=mp.begin();i!=mp.end();i++)
{
p=i->first;
a=i->s;
sum=sum*((pow(p,a+1)-1)/(p-1));
}
如果(总和=2*num)
printf(“完美的”);
else if(sum>num)
printf(“丰富的”\n);
其他的
printf(“缺陷”\n);
mp.clear();
}
返回0;
}
//确定是否完美的程序
#包括
使用名称空间std;
map mp;//存储基本因子和频率
空隙系数(长整型n)
{
//计算除以n的2的数量
而(n%2==0)
{
mp[2]=mp[2]+1;
n=n/2;
}
长整数根=sqrt(n);
//n在这一点上一定是奇数,所以我们可以跳过所有偶数
用于(长整型i=3;i 2)
{
mp[n]=mp[n]+1;
}
}
长整型战力(长整型基地,长整型经验)
{
长整型结果=1;
基数=基数;
而(exp>0)
{
if(exp&1)
结果=(结果*基础);
exp>>=1;
基数=(基数*基数);
}
返回结果;
}
int main()
{
long-long-num,p,a,sum;
while(scanf(“%lld”,&num)!=EOF&&num)
{
原始因子(num);
// 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;
}