【问题标题】:HackerRank Project Euler #21: Amicable numbersHackerRank Project Euler #21:友好数字
【发布时间】:2015-06-02 11:15:38
【问题描述】:

Here 是问题陈述。

d(n) 定义为 n 的真因数之和(小于 n 的数均分为 n)。

如果 d(a)=bd(b)=a,其中 a≠b,则 a 和 b 是a 和 b 中的每一个都称为友好数。

例如,220 的真因数是 1、2、4、5、10、11、20、22、44、55 和 110,因此 d(220)=284。 284 的真因数是 1、2、4、71 和 142,所以 d(284)=220。

求N下所有亲和数之和。

这是我的蛮力代码

#include <stdio.h>

long long int sum(long long int n)
{
    long long int i, sum=0;
    for(i=1;i<n;i++)
    {
        if(n%i==0)
            sum+=i;
    }
    return sum;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long int n;
        scanf("%lld",&n);
        long long int i,sum1=0;
        for(i=1;i<n;i++)
        {
            if(sum(sum(i))==i&&sum(i)!=i)
                sum1+=i;
        }
        printf("%lld\n",sum1);
    }
    return 0;
}

此代码有效,但速度很慢。因此,我实现了一个更快的算法。

该算法将找到其主要因子的除数之和并将它们相乘。该算法的证明here。这是代码。

#include <stdio.h>

long long int power(long long int x, long long int y)
{
    long long int i,a=1;
    for(i=1;i<=y;i++)
        a*=x;
    return a;
}

long long int sumOfPrimeDivisors(long long int p, long long int a)
{
    long long int x;
    x=(power(p,a+1)-1)/(p-1);
    return x;
}

long long int isPrime(long long int n)
{
    long long int i,flag=1;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            flag=0;
            break;
        }
    }
    return flag;
}

void primeDivisors(long long int n, long long int b[], int *k)
{
    long long int i;
    *k=0;
    for(i=2;i<n;i++)
    {
        if(n%i==0 && isPrime(i))
        {
        b[(*k)++]=i;
        }
    }
}

long long int primeDivisorCount(long long int n, long long int p)
{
    long long int count=0;
    while(n%p==0)
    {
        count++;
        n/=p;
    }
    return count;
}

long long int sum(long long int n)
{
    long long int ans=1,b[15];
    int k,i;

    primeDivisors(n,b,&k);

    for(i=0;i<k;i++)
        ans*=sumOfPrimeDivisors(b[i],primeDivisorCount(n,b[i]));

    return ans-n;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long int n;
        scanf("%lld",&n);

        printf("%lld %lld\n",sum(n),sum(sum(n)));
    }

    return 0;
}

此代码为n=220 (284 220) 提供正确的输出。但是当我用

替换printf
long long int i;

        for(i=1;i<n;i++)
        {
            if(sum(sum(i))==i && sum(i)!=i )
                printf("%lld\n",i);
        }

我得到了输出的所有垃圾值。

例如,

输入

1
9949

输出

-9948

我做错了什么?

【问题讨论】:

  • 您的代码打印了哪些不应该包含的数字? sum(i)sum(sum(i)) 为这些数字提供了什么?
  • 我得到了很多 i 的垃圾值。其中之一是9949 给出输出-9948 9949

标签: c


【解决方案1】:

变化

if(sum(sum(i))==i && sum(i)!=i )

if(sum(sum(i))==i && sum(i)!=i && sum(i)>0)

有助于提供正确的输出。

【讨论】:

  • 这只是解决给你负数的错误,而不是修复它。
【解决方案2】:

用这个代替 printf :

   long long int i; 
    for(i=1;i<n;i++)
    {
        if(sum(sum(i))==i && sum(i)!=i && !isPrime(i))
            printf("%lld\n",i);
    }

以前所有其他素数也会显示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2013-03-24
    • 2021-12-23
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多