给定一个数字N ,任务是找到从1到N的数字的所有理想平方除数的总和。
例子:
Input: N = 5
Output: 9
Explanation: N = 5
Perfect square divisors of 1 = 1.
Similarly, perfect square divisors of 2, 3 = 1.
Perfect square divisors of 4 = 1, 4.
Perfect square divisors of 5 = 1 (of course for any prime only 1 will be the perfect square divisor)
So, total sum = 1+1+1+(1+4)+1 = 9.
Input: N = 30
Output: 126
Input: N = 100
Output: 910
天真的方法:此方法基于本文中实现的方法
对于任何第K个功率除数,上述问题都可以用O(N 1 / k )来解决,其中N是我们必须求和的总和。这是因为,以这个总和,每个数字都将贡献下限(N / p)或int(N / p)次。因此,当迭代这些完美的幂时,我们只需要将[p * int(N / p)]加到总和上即可。
时间复杂度: O(√N)
高效方法:
- 让我们从start = 2开始,找到floor(N /(start 2 ))= floor(N /(end 2 ))的最大范围(开始到结束)
- 在间隔[start,end]中所有理想平方的贡献将贡献floor(N /(start 2 ))次,因此我们可以立即对此范围进行更新。
- 范围[开始,结束]的贡献可以表示为:
floor(N/(start2))*(sumUpto(end) – sumUpto(start-1))
- 如何找到范围?
对于给定的开始值,可以通过以下方式找到结束
sqrt(N/K), where K = floor(N/(start^2))
- 现在,可以通过替换start = end + 1来找到下一个范围。
时间复杂性:O(N 1/3)为N /(×2)不能采取多于N个1/3不同的值N的固定值。
下面是上述方法的实现:
C++
// C++ Program to find the
// sum of all perfect square
// divisors of numbers from 1 to N
#include
using namespace std;
#define MOD 1000000007
#define int unsigned long long
// Function for finding inverse
// of a number iteratively
// Here we will find the inverse
// of 6, since it appears as
// denominator in the formula of
// sum of squares from 1 to N
int inv(int a)
{
int o = 1;
for (int p = MOD - 2;
p > 0; p >>= 1) {
if ((p & 1) == 1)
o = (o * a) % MOD;
a = (a * a) % MOD;
}
return o;
}
// Store the value of the inverse
// of 6 once as we don't need to call
// the function again and again
int inv6 = inv(6);
// Formula for finding the sum
// of first n squares
int sumOfSquares(int n)
{
n %= MOD;
return (((n * (n + 1))
% MOD * (2 * n + 1))
% MOD * inv6)
% MOD;
}
int sums(int n)
{
// No perfect square
// exists which is
// less than 4
if (n < 4)
return 0;
// Starting from 2, present value
// of start is denoted here as
// curStart
int curStart = 2, ans = 0;
int sqrtN = sqrt(n);
while (curStart <= n / curStart) {
int V = n / (curStart * curStart);
// Finding end of the segment
// for which the contribution
// will be same
int end = sqrt(n / V);
// Using the above mentioned
// formula to find ans % MOD
ans += (n / (curStart * curStart)
% MOD * (sumOfSquares(end)
+ MOD
- sumOfSquares(curStart - 1)))
% MOD;
if (ans >= MOD)
ans -= MOD;
// Now for mthe next iteration
// start will become end+1
curStart = end + 1;
}
// Finally returning the answer
return ans;
}
// Driver Code
int32_t main()
{
int input[] = { 5 };
for (auto x : input) {
cout << "sum of all perfect"
<< " square divisors from"
<< " 1 to " << x
<< " is: ";
// Here we are adding x
// because we have not
// counted 1 as perfect
// squares so if u want to
// add it you can just add
// that number to the ans
cout << x + sums(x) << endl;
}
return 0;
}
Java
// Java program to find the
// sum of all perfect square
// divisors of numbers from 1 to N
import java.util.*;
class GFG{
static final int MOD = 7;
// Function for finding inverse
// of a number iteratively
// Here we will find the inverse
// of 6, since it appears as
// denominator in the formula of
// sum of squares from 1 to N
static int inv(int a)
{
int o = 1;
for(int p = MOD - 2;
p > 0; p >>= 1)
{
if ((p & 1) == 1)
o = (o * a) % MOD;
a = (a * a) % MOD;
}
return o;
}
// Store the value of the inverse
// of 6 once as we don't need to call
// the function again and again
static int inv6 = inv(6);
// Formula for finding the sum
// of first n squares
static int sumOfSquares(int n)
{
n %= MOD;
return (((n * (n + 1)) %
MOD * (2 * n + 1)) %
MOD * inv6) % MOD;
}
static int sums(int n)
{
// No perfect square
// exists which is
// less than 4
if (n < 4)
return 0;
// Starting from 2, present value
// of start is denoted here as
// curStart
int curStart = 2, ans = 0;
int sqrtN = (int)Math.sqrt(n);
while (curStart <= n / curStart)
{
int V = n / (curStart * curStart);
// Finding end of the segment
// for which the contribution
// will be same
int end = (int)Math.sqrt(n / V);
// Using the above mentioned
// formula to find ans % MOD
ans += (n / (curStart * curStart) %
MOD * (sumOfSquares(end) + MOD -
sumOfSquares(curStart - 1))) % MOD;
if (ans >= MOD)
ans -= MOD;
// Now for mthe next iteration
// start will become end+1
curStart = end + 1;
}
// Finally returning the answer
return ans;
}
// Driver Code
public static void main(String[] args)
{
int input[] = {5};
for(int x : input)
{
System.out.print("sum of all perfect " +
"square divisors from " +
"1 to " + x + " is: ");
// Here we are adding x
// because we have not
// counted 1 as perfect
// squares so if u want to
// add it you can just add
// that number to the ans
System.out.print(x + sums(x) + "\n");
}
}
}
// This code is contributed by Amit Katiyar
Python3
# Python3 program to find the
# sum of all perfect square
# divisors of numbers from 1 to N
from math import *
MOD = 1000000007
# Function for finding inverse
# of a number iteratively
# Here we will find the inverse
# of 6, since it appears as
# denominator in the formula of
# sum of squares from 1 to N
def inv (a):
o = 1
p = MOD - 2
while (p > 0):
if (p % 2 == 1):
o = (o * a) % MOD
a = (a * a) % MOD
p >>= 1
return o
# Store the value of the inverse
# of 6 once as we don't need to call
# the function again and again
inv6 = inv(6)
# Formula for finding the sum
# of first n squares
def sumOfSquares (n):
n %= MOD
return (((n * (n + 1)) %
MOD * (2 * n + 1)) %
MOD * inv6) % MOD
def sums (n):
# No perfect square exists which
# is less than 4
if (n < 4):
return 0
# Starting from 2, present value
# of start is denoted here as curStart
curStart = 2
ans = 0
sqrtN = int(sqrt(n))
while (curStart <= n // curStart):
V = n // (curStart * curStart)
# Finding end of the segment for
# which the contribution will be same
end = int(sqrt(n // V))
# Using the above mentioned
# formula to find ans % MOD
ans += ((n // (curStart * curStart) %
MOD * (sumOfSquares(end) +
MOD - sumOfSquares(curStart - 1))) % MOD)
if (ans >= MOD):
ans -= MOD
# Now for mthe next iteration
# start will become end+1
curStart = end + 1
# Finally return the answer
return ans
# Driver Code
if __name__ == '__main__':
Input = [5]
for x in Input:
print("sum of all perfect "\
"square " , end = '')
print("divisors from 1 to", x,
"is: ", end = '')
# Here we are adding x because we have
# not counted 1 as perfect squares so if u
# want to add it you can just add that
# number to the ans
print(x + sums(x))
# This code is contributed by himanshu77
C#
// C# program to find the
// sum of all perfect square
// divisors of numbers from 1 to N
using System;
class GFG{
static readonly int MOD = 7;
// Function for finding inverse
// of a number iteratively
// Here we will find the inverse
// of 6, since it appears as
// denominator in the formula of
// sum of squares from 1 to N
static int inv(int a)
{
int o = 1;
for(int p = MOD - 2;
p > 0; p >>= 1)
{
if ((p & 1) == 1)
o = (o * a) % MOD;
a = (a * a) % MOD;
}
return o;
}
// Store the value of the inverse
// of 6 once as we don't need to call
// the function again and again
static int inv6 = inv(6);
// Formula for finding the sum
// of first n squares
static int sumOfSquares(int n)
{
n %= MOD;
return (((n * (n + 1)) %
MOD * (2 * n + 1)) %
MOD * inv6) % MOD;
}
static int sums(int n)
{
// No perfect square
// exists which is
// less than 4
if (n < 4)
return 0;
// Starting from 2, present
// value of start is denoted
// here as curStart
int curStart = 2, ans = 0;
int sqrtN = (int)Math.Sqrt(n);
while (curStart <= n / curStart)
{
int V = n / (curStart * curStart);
// Finding end of the segment
// for which the contribution
// will be same
int end = (int)Math.Sqrt(n / V);
// Using the above mentioned
// formula to find ans % MOD
ans += (n / (curStart * curStart) %
MOD * (sumOfSquares(end) + MOD -
sumOfSquares(curStart -
1))) % MOD;
if (ans >= MOD)
ans -= MOD;
// Now for mthe next iteration
// start will become end+1
curStart = end + 1;
}
// Finally returning
// the answer
return ans;
}
// Driver Code
public static void Main(String[] args)
{
int []input = {5};
foreach(int x in input)
{
Console.Write("sum of all perfect " +
"square divisors from " +
"1 to " + x + " is: ");
// Here we are adding x
// because we have not
// counted 1 as perfect
// squares so if u want to
// add it you can just add
// that number to the ans
Console.Write(x + sums(x) + "\n");
}
}
}
// This code is contributed by Rajput-Ji
sum of all perfect square divisors from 1 to 5 is: 9
时间复杂度: O(N 1/3 )
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。