📌  相关文章
📜  数从1到N的所有理想平方除数的总和

📅  最后修改于: 2021-04-29 11:51:38             🧑  作者: Mango

给定一个数字N ,任务是找到从1N的数字的所有理想平方除数的总和。
例子:

天真的方法:此方法基于本文中实现的方法
对于任何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 ))次,因此我们可以立即对此范围进行更新。
  • 范围[开始,结束]的贡献可以表示为:
  • 如何找到范围?
    对于给定的开始值,可以通过以下方式找到结束
  • 现在,可以通过替换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 )