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
我做错了什么?
答案 0 :(得分:2)
更改
if(sum(sum(i))==i && sum(i)!=i )
到
if(sum(sum(i))==i && sum(i)!=i && sum(i)>0)
帮助提供正确的输出。
答案 1 :(得分:1)
使用此代替printf:
{{1}}
以前所有其他素数也都在显示。