给定正整数N ,任务是找到前N个自然数的除数之和。
例子:
Input: N = 4
Output: 15
Explanation:
Sum of divisors of 1 = (1)
Sum of divisors of 2 = (1+2)
Sum of divisors of 3 = (1+3)
Sum of divisors of 4 = (1+2+4)
Hence, total sum = 1 + (1+2) + (1+3) + (1+2+4) = 15
Input: N = 5
Output: 21
Explanation:
Sum of divisors of 1 = (1)
Sum of divisors of 2 = (1+2)
Sum of divisors of 3 = (1+3)
Sum of divisors of 4 = (1+2+4)
Sum of divisors of 5 = (1+5)
Hence, total sum = (1) + (1+2) + (1+3) + (1+2+4) + (1+5) = 21
对于线性时间方法,请参阅从1到N的所有除数之和
方法:
为了优化上述文章中的方法,我们需要寻找具有对数复杂度的解决方案。在最终答案中,数字D被多次添加。让我们尝试观察重复加法的模式。
考虑N = 12 :
D | Number of times added |
---|---|
1 | 12 |
2 | 6 |
3 | 4 |
5, 6 | 2 |
7, 8, 9, 10, 11, 12 | 1 |
从上面的模式中,观察到每个数字D被添加( N / D )次。另外,有多个具有相同(N / D)的D。因此,我们可以得出结论,对于给定的N和特定的i ,将从( N /( i + 1 ))+ 1到( N / i )的数字相加i次。
Illustration:
- N = 12, i = 1
(N/(i+1))+1 = 6+1 = 7 and (N/i) = 12
All numbers will be 7, 8, 9, 10, 11, 12 and will be added 1 time only. - N = 12, i = 2
(N/(i+1))+1 = 4+1 = 5 and (N/i) = 6
All numbers will be 5, 6 and will be added 2 times.
现在,假设A =(N /(i + 1)), B =(N / i)
从A到1的数字总和=从1到B的数字总和–从1到A的数字总和
另外,不仅仅是每次将i递增1,而是查找下一个像这样的i,i = N /(N /(i + 1))
下面是上述方法的实现:
C++
// C++ program for
// the above approach
#include
using namespace std;
int mod = 1000000007;
// Functions returns sum
// of numbers from 1 to n
int linearSum(int n)
{
return (n * (n + 1) / 2) % mod;
}
// Functions returns sum
// of numbers from a+1 to b
int rangeSum(int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
// Function returns total
// sum of divisors
int totalSum(int n)
{
// Stores total sum
int result = 0;
int i = 1;
// Finding numbers and
//its occurence
while(true)
{
// Sum of product of each
// number and its occurence
result += rangeSum(n / i, n / (i + 1)) *
(i % mod) % mod;
result %= mod;
if (i == n)
break;
i = n / (n / (i + 1));
}
return result;
}
// Driver code
int main()
{
int N = 4;
cout << totalSum(N) << endl;
N = 12;
cout << totalSum(N) << endl;
return 0;
}
// This code is contributed by rutvik_56
Java
// Java program for
// the above approach
class GFG{
static final int mod = 1000000007;
// Functions returns sum
// of numbers from 1 to n
public static int linearSum(int n)
{
return (n * (n + 1) / 2) % mod;
}
// Functions returns sum
// of numbers from a+1 to b
public static int rangeSum(int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
// Function returns total
// sum of divisors
public static int totalSum(int n)
{
// Stores total sum
int result = 0;
int i = 1;
// Finding numbers and
//its occurence
while(true)
{
// Sum of product of each
// number and its occurence
result += rangeSum(n / i,
n / (i + 1)) *
(i % mod) % mod;
result %= mod;
if (i == n)
break;
i = n / (n / (i + 1));
}
return result;
}
// Driver code
public static void main(String[] args)
{
int N = 4;
System.out.println(totalSum(N));
N = 12;
System.out.println(totalSum(N));
}
}
// This code is contributed by divyeshrabadiya07
Python3
# Python3 program for
# the above approach
mod = 1000000007
# Functions returns sum
# of numbers from 1 to n
def linearSum(n):
return n*(n + 1)//2 % mod
# Functions returns sum
# of numbers from a+1 to b
def rangeSum(b, a):
return (linearSum(b) - (
linearSum(a))) % mod
# Function returns total
# sum of divisors
def totalSum(n):
# Stores total sum
result = 0
i = 1
# Finding numbers and
# its occurence
while True:
# Sum of product of each
# number and its occurence
result += rangeSum(
n//i, n//(i + 1)) * (
i % mod) % mod;
result %= mod;
if i == n:
break
i = n//(n//(i + 1))
return result
# Driver code
N= 4
print(totalSum(N))
N= 12
print(totalSum(N))
C#
// C# program for
// the above approach
using System;
class GFG{
static readonly int mod = 1000000007;
// Functions returns sum
// of numbers from 1 to n
public static int linearSum(int n)
{
return (n * (n + 1) / 2) % mod;
}
// Functions returns sum
// of numbers from a+1 to b
public static int rangeSum(int b, int a)
{
return (linearSum(b) -
linearSum(a)) % mod;
}
// Function returns total
// sum of divisors
public static int totalSum(int n)
{
// Stores total sum
int result = 0;
int i = 1;
// Finding numbers and
//its occurence
while(true)
{
// Sum of product of each
// number and its occurence
result += rangeSum(n / i,
n / (i + 1)) *
(i % mod) % mod;
result %= mod;
if (i == n)
break;
i = n / (n / (i + 1));
}
return result;
}
// Driver code
public static void Main(String[] args)
{
int N = 4;
Console.WriteLine(totalSum(N));
N = 12;
Console.WriteLine(totalSum(N));
}
}
// This code is contributed by Amit Katiyar
15
127
时间复杂度: O(log N)