给定自然数n(1 <= n <= 500000),请输出所有适当除数的总和。
定义:自然数的适当除数是严格小于数的除数。
e.g。数字20有5个适当的除数:1,2,4,5,10,除数求和为:1 + 2 + 4 + 5 + 10 = 22。 &lt;&lt; - 这是我想要做的挑战,我正在使用递归
int find_sum(std::vector <int> nums,long int sum,int num_now,long int j)
{
if(j<nums[num_now])
{
if(nums[num_now]%j==0)
{
sum=sum+j;
}
return find_sum(nums,sum,num_now,j+1);
}
else
{
return sum;
}
}
sum是所有除数的总和,nums是我存储的数字的向量,num_now是向量中的当前成员,int j是1我用它来搜索分隔符,遗憾地使用这个我不能使用像500000这样的数字它给出& #39;我的错误,有没有更好的办法,或者我在某个地方犯了错误。
- 谢谢您的时间
答案 0 :(得分:2)
这是解决问题的递归方法:
User.where(:_id => "one of your users").includes(:party).first
您需要致电int find_sum(int x, int i)
{
if(i == 0)
return 0;
if(x % i == 0)
return i + find_sum(x, (i-1));
return find_sum(x, (i-1));
}
以查找N的分隔符总和(find_sum(N, N-1);
必须小于给定的i
,因为严格的不等式)。
在您的情况下,它将是N
e.g。我的函数返回:
find_sum(20, 19);
71086
N = 50000
22
N = 20
0
答案 1 :(得分:1)
我没有看到你需要使用递归来解决这个问题的原因。我宁愿采用更直观的方式来解决它。
long CalculateSumOfDivisors(int number)
{
long sum = 0;
for(int i=1; i<number; i++)
{
// If the remainder of num/i is zero
// then i divides num. So we add it to the
// current sum.
if(number%i==0)
{
sum+=i;
}
}
return sum;
}
此外,如果我们注意以下内容,我们可以编写更优的算法:
假设我们有一个数n和d是n的最大除数,它是1的最大除数。(显然,如果数n是素数,则存在任何这样的除数)。然后n的大除数是数字n / d。
基于此,我们可以制定更优化的算法。
long CalculateSumOfDivisors(int number)
{
int smallestDivisor = FindSmallestDivisor(number);
if(smallestDivisor==1) return 1;
long sum = smallestDivisor;
// Calculate the possible greatest divisor.
int possibleGreatestDivisor = (int)floor(number/smallestDivisor);
for(int i=smallestDivisor+1; i<=possibleGreatestDivisor; i++)
{
if(number%i==0)
{
sum+=i;
}
}
return sum;
}
int FindSmallestDivisor(int number)
{
int smallestDivisor = 1;
for(int i=2; i<number; i++)
{
if(number%i==0)
{
smallestDivisor = i;
break;
}
}
return smallestDivisor;
}
答案 2 :(得分:0)
我认为你不应该使用递归。
而是从1..N-1
循环开始当您找到除数时,调整循环的结束值。例如,如果2是除数,那么你知道N / 2也是一个除数。同样重要的是你知道在这个范围内不会有更多的除数] N / 2:N [。同样,如果3是除数,那么你知道N / 3也是一个除数,你知道范围内没有更多的除数] N / 3:N [。
遵循这一概念,您可以显着减少大多数数字的循环次数。
类似的东西:
long find_sum(int num)
{
long sum = 0;
int max = num;
int i = 1;
while(i < max)
{
if(num % i == 0)
{
sum += i; // Add i to the sum
max = num / i; // Decrement max for performance
if (max != i && max != num)
{
sum += max; // Add max when max isn't equal i
}
}
i++;
}
return sum;
}
示例:
num = 10
sum = 0
i = 1 -> sum = 1, max = 10
i = 2 -> sum = 1+2+5, max = 5
i = 3 -> sum = 1+2+5, max = 5
i = 4 -> sum = 1+2+5, max = 5
i = 5 -> return 8 (1+2+5)
num = 64
sum = 0
i = 1 -> sum = 1, max = 64
i = 2 -> sum = 1+2+32, max = 32
i = 3 -> sum = 1+2+32, max = 32
i = 4 -> sum = 1+2+32+4+16, max = 16
i = 5 -> sum = 1+2+32+4+16, max = 16
i = 6 -> sum = 1+2+32+4+16, max = 16
i = 7 -> sum = 1+2+32+4+16, max = 16
i = 8 -> sum = 1+2+32+4+16+8, max = 8
i = 9 -> return (1+2+32+4+16+8)
每当找到新的除数时,通过更改max
来保持循环次数。
答案 3 :(得分:0)
我尝试用main函数编写代码,要求用户给它想要得到的总和。这是代码,希望它有所帮助。
#include<iostream>
using namespace std;
int Sum(int min, int max, int &val, int &sum){
if(min >= max)
return 0;
for ( ; min < max; min++){
if ( val%min == 0){
sum += min + val/min;
return Sum(++min,val/min, val,sum);
}
}
return 0;
}
int main(){
int s=1;
int val;
cout <<"Enter Val to sum:";
cin >> val;
Sum(2,val,val,s);
cout <<"Sum is :"<<s<<endl;
return 0;
}
这里Sum函数以递归方式使用并传递参数,如代码所示。
希望它有所帮助。