【发布时间】:2015-06-02 11:15:38
【问题描述】:
Here 是问题陈述。
让 d(n) 定义为 n 的真因数之和(小于 n 的数均分为 n)。
如果 d(a)=b 且 d(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