📜  所有可能序列的 GCD 之和

📅  最后修改于: 2021-09-17 07:40:40             🧑  作者: Mango

给定两个数字NK 。可以通过在每个位置放置从1 到 K 的数字来创建长度为N的序列A 1 , A 2 , ….A N ,总共有 K N 个序列。任务是找到所有形成的序列的 GCD 之和。
注意:答案可能很大,所以取模10 9 + 7

例子:

朴素的方法:这个想法是递归地生成长度为N 的所有可能的子序列。所形成的所有序列的 GCD 之和就是所需的结果。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
 
const int MOD = (int)1e9 + 7;
 
// A recursive function that generates all
// the sequence and find GCD
int calculate(int pos, int g, int n, int k)
{
 
    // If we reach the sequence of length N
    // g is the GCD of the sequence
    if (pos == n) {
        return g;
    }
 
    // Initialise answer to 0
    int answer = 0;
 
    // Placing all possible values at this
    // position and recursively find the
    // GCD of the sequence
    for (int i = 1; i <= k; i++) {
 
        // Take GCD of GCD calculated uptill
        // now i.e. g with current element
        answer = (answer % MOD
                  + calculate(pos + 1, __gcd(g, i), n, k) % MOD);
 
        // Take modulo to avoid overflow
        answer %= MOD;
    }
 
    // Return the final answer
    return answer;
}
 
// Function that finds the sum of GCD
// of all the subsequence of N length
int sumofGCD(int n, int k)
{
 
    // Recursive function that generates
    // the sequence and return the GCD
    return calculate(0, 0, n, k);
}
 
// Driver Code
int main()
{
    int N = 3, K = 2;
 
    // Function Call
    cout << sumofGCD(N, K);
    return 0;
}


Java
// Java implementation of the above approach
class GFG{
  
static int MOD = (int)1e9 + 7;
  
// A recursive function that generates all
// the sequence and find GCD
static int calculate(int pos, int g, int n, int k)
{
  
    // If we reach the sequence of length N
    // g is the GCD of the sequence
    if (pos == n) {
        return g;
    }
  
    // Initialise answer to 0
    int answer = 0;
  
    // Placing all possible values at this
    // position and recursively find the
    // GCD of the sequence
    for (int i = 1; i <= k; i++) {
  
        // Take GCD of GCD calculated uptill
        // now i.e. g with current element
        answer = (answer % MOD
                  + calculate(pos + 1, __gcd(g, i), n, k) % MOD);
  
        // Take modulo to astatic void overflow
        answer %= MOD;
    }
  
    // Return the final answer
    return answer;
}
  
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
  
    // Recursive function that generates
    // the sequence and return the GCD
    return calculate(0, 0, n, k);
}
 
static int __gcd(int a, int b) 
{ 
    return b == 0? a:__gcd(b, a % b);    
}
// Driver Code
public static void main(String[] args)
{
    int N = 3, K = 2;
  
    // Function Call
    System.out.print(sumofGCD(N, K));
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Pyhton3 implementation of the
# above approach
MOD = 1e9 + 7
 
def gcd(a, b):
     
    if (b == 0):
        return a
    else:
        return gcd(b, a % b)
 
# A recursive function that generates all
# the sequence and find GCD
def calculate(pos, g, n, k):
  
    # If we reach the sequence of length N
    # g is the GCD of the sequence
    if (pos == n):
        return g
  
    # Initialise answer to 0
    answer = 0
  
    # Placing all possible values at this
    # position and recursively find the
    # GCD of the sequence
    for i in range(1, k + 1):
  
        # Take GCD of GCD calculated uptill
        # now i.e. g with current element
        answer = (answer % MOD +
                  calculate(pos + 1,
                            gcd(g, i), n, k) % MOD)
  
        # Take modulo to avoid overflow
        answer %= MOD
     
    # Return the final answer
    return answer
  
# Function that finds the sum of GCD
# of all the subsequence of N length
def sumofGCD(n, k):
  
    # Recursive function that generates
    # the sequence and return the GCD
    return calculate(0, 0, n, k)
 
# Driver code   
if __name__=="__main__":
     
    N = 3
    K = 2
  
    # Function Call
    print(sumofGCD(N, K))
 
# This code is contributed by rutvik_56


C#
// C# implementation of the above approach
using System;
 
public class GFG{
 
static int MOD = (int)1e9 + 7;
 
// A recursive function that generates all
// the sequence and find GCD
static int calculate(int pos, int g, int n, int k)
{
     
    // If we reach the sequence of length N
    // g is the GCD of the sequence
    if (pos == n) {
        return g;
    }
 
    // Initialise answer to 0
    int answer = 0;
 
    // Placing all possible values at this
    // position and recursively find the
    // GCD of the sequence
    for (int i = 1; i <= k; i++) {
 
        // Take GCD of GCD calculated uptill
        // now i.e. g with current element
        answer = (answer % MOD
                  + calculate(pos + 1, __gcd(g, i), n, k) % MOD);
 
        // Take modulo to astatic void overflow
        answer %= MOD;
    }
 
    // Return the readonly answer
    return answer;
}
 
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
 
    // Recursive function that generates
    // the sequence and return the GCD
    return calculate(0, 0, n, k);
}
 
static int __gcd(int a, int b)
{
    return b == 0 ? a : __gcd(b, a % b);    
}
 
// Driver code
public static void Main(String[] args)
{
    int N = 3, K = 2;
 
    // Function call
    Console.Write(sumofGCD(N, K));
}
}
 
// This code is contributed by 29AjayKumar


Javascript


C++
// C++ implementation of the above approach
#include 
using namespace std;
const int MOD = (int)1e9 + 7;
 
// Function to find a^b in log(b)
int fastexpo(int a, int b)
{
 
    int res = 1;
    a %= MOD;
 
    while (b) {
        if (b & 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
 
// Function that finds the sum of GCD
// of all the subsequence of N length
int sumofGCD(int n, int k)
{
 
    // To stores the number of sequences
    // with gcd i
    int count[k + 1] = { 0 };
 
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
 
        // To count multiples
        int count_multiples = k / g;
 
        // possible sequences with
        // overcounting
        int temp;
 
        temp = fastexpo(count_multiples, n);
 
        // to avoid overflow
        temp %= MOD;
 
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
 
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
 
            extra = (extra + count[j]);
            extra %= MOD;
        }
 
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
 
    // To store the final answer
    int sum = 0;
    int add;
 
    for (int i = 1; i <= k; ++i) {
 
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
 
    // Return Final answer
    return sum;
}
 
// Driver Code
int main()
{
    int N = 3, K = 2;
 
    // Function call
    cout << sumofGCD(N, K);
    return 0;
}


Java
// Java implementation of the above approach
class GFG{
static int MOD = (int)1e9 + 7;
  
// Function to find a^b in log(b)
static int fastexpo(int a, int b)
{
  
    int res = 1;
    a %= MOD;
  
    while (b > 0) {
        if (b % 2 == 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
  
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
  
    // To stores the number of sequences
    // with gcd i
    int []count = new int[k + 1];
  
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
  
        // To count multiples
        int count_multiples = k / g;
  
        // possible sequences with
        // overcounting
        int temp;
  
        temp = fastexpo(count_multiples, n);
  
        // to astatic void overflow
        temp %= MOD;
  
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
  
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
  
            extra = (extra + count[j]);
            extra %= MOD;
        }
  
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
  
    // To store the final answer
    int sum = 0;
    int add;
  
    for (int i = 1; i <= k; ++i) {
  
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
  
    // Return Final answer
    return sum;
}
  
// Driver Code
public static void main(String[] args)
{
    int N = 3, K = 2;
  
    // Function call
    System.out.print(sumofGCD(N, K));
}
}
 
// This code is contributed by PrinciRaj1992


Python3
# Python3 implementation of the above approach
MOD = (int)(1e9 + 7)
 
# Function to find a^b in log(b)
def fastexpo(a, b) :
    res = 1
    a = a % MOD
    while (b > 0) :
        if ((b & 1) != 0) :
            res = (res * a) % MOD
        a = a * a
        a = a % MOD
        b = b >> 1
    return res
 
# Function that finds the sum of GCD
# of all the subsequence of N length
def sumofGCD(n, k) :
     
    # To stores the number of sequences
    # with gcd i
    count = [0] * (k + 1)
 
    # Find contribution of each gcd
    # to happen
    for g in range(k, 0, -1) :
 
        # To count multiples
        count_multiples = k // g
 
        # possible sequences with
        # overcounting
        temp = fastexpo(count_multiples, n)
 
        # to avoid overflow
        temp = temp % MOD
 
        # Find extra element which will
        # not form gcd = i
        extra = 0
 
        # Find overcounting
        for j in range(g * 2, k + 1, g) :
            extra = extra + count[j]
            extra = extra % MOD
 
        # Remove the overcounting
        count[g] = temp - extra + MOD
        count[g] = count[g] % MOD
 
    # To store the final answer
    Sum = 0
    for i in range(1, k + 1) :
        add = count[i] % MOD * i % MOD
        add = add % MOD
        Sum = Sum + add
        Sum = Sum % MOD
 
    # Return Final answer
    return Sum
 
  # Driver code
N, K = 3, 2
 
# Function call
print(sumofGCD(N, K))
 
# This code is contributed by divyeshrabadiya07.


C#
// C# implementation of the above approach
using System;
 
class GFG{
static int MOD = (int)1e9 + 7;
   
// Function to find a^b in log(b)
static int fastexpo(int a, int b)
{
   
    int res = 1;
    a %= MOD;
   
    while (b > 0) {
        if (b % 2 == 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
   
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
   
    // To stores the number of sequences
    // with gcd i
    int []count = new int[k + 1];
   
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
   
        // To count multiples
        int count_multiples = k / g;
   
        // possible sequences with
        // overcounting
        int temp;
   
        temp = fastexpo(count_multiples, n);
   
        // to astatic void overflow
        temp %= MOD;
   
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
   
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
   
            extra = (extra + count[j]);
            extra %= MOD;
        }
   
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
   
    // To store the readonly answer
    int sum = 0;
    int add;
   
    for (int i = 1; i <= k; ++i) {
   
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
   
    // Return Final answer
    return sum;
}
   
// Driver Code
public static void Main(String[] args)
{
    int N = 3, K = 2;
   
    // Function call
    Console.Write(sumofGCD(N, K));
}
}
 
// This code is contributed by Princi Singh


Javascript


输出:
9

时间复杂度: O(N K )

有效的方法:

  • 由于序列的编号可以从1 到 K ,因此序列的 gcd 值将在 1 到 K 的范围内。
  • count[i]表示 gcd = i 的序列数。对于 i = 1,我们对哪些元素可以属于该序列没有限制,因此在N 个位置中的每一个,我们都有K 个放置元素的可能性,使总序列成为K N 。但是得到的序列可能有更高的 GCD,所以减去过度计数的值:
count[1] = KN - count[2] - count[3] - count[4] - .... count[K]
  • 类似地,对于 i = 2,由于每个数字都必须是 2 的倍数,因此我们在每个位置都有K/2 种可能性,使总数为(K/2) N 。并通过用所有 2 的倍数的 GCD 减去序列计数来减去所有过度计数的值。
count[2] = (K/2)N - count[4] - count[6] - count[8] - ... all multiples of 2
  • 类似地,对每个gcd值按照上述步骤到K。
  • 每个 GCD 值(比如g )与count[g]的总和是所有形成的序列的 GCD 之和。

下面是上述方法的实现:

C++

// C++ implementation of the above approach
#include 
using namespace std;
const int MOD = (int)1e9 + 7;
 
// Function to find a^b in log(b)
int fastexpo(int a, int b)
{
 
    int res = 1;
    a %= MOD;
 
    while (b) {
        if (b & 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
 
// Function that finds the sum of GCD
// of all the subsequence of N length
int sumofGCD(int n, int k)
{
 
    // To stores the number of sequences
    // with gcd i
    int count[k + 1] = { 0 };
 
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
 
        // To count multiples
        int count_multiples = k / g;
 
        // possible sequences with
        // overcounting
        int temp;
 
        temp = fastexpo(count_multiples, n);
 
        // to avoid overflow
        temp %= MOD;
 
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
 
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
 
            extra = (extra + count[j]);
            extra %= MOD;
        }
 
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
 
    // To store the final answer
    int sum = 0;
    int add;
 
    for (int i = 1; i <= k; ++i) {
 
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
 
    // Return Final answer
    return sum;
}
 
// Driver Code
int main()
{
    int N = 3, K = 2;
 
    // Function call
    cout << sumofGCD(N, K);
    return 0;
}

Java

// Java implementation of the above approach
class GFG{
static int MOD = (int)1e9 + 7;
  
// Function to find a^b in log(b)
static int fastexpo(int a, int b)
{
  
    int res = 1;
    a %= MOD;
  
    while (b > 0) {
        if (b % 2 == 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
  
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
  
    // To stores the number of sequences
    // with gcd i
    int []count = new int[k + 1];
  
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
  
        // To count multiples
        int count_multiples = k / g;
  
        // possible sequences with
        // overcounting
        int temp;
  
        temp = fastexpo(count_multiples, n);
  
        // to astatic void overflow
        temp %= MOD;
  
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
  
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
  
            extra = (extra + count[j]);
            extra %= MOD;
        }
  
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
  
    // To store the final answer
    int sum = 0;
    int add;
  
    for (int i = 1; i <= k; ++i) {
  
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
  
    // Return Final answer
    return sum;
}
  
// Driver Code
public static void main(String[] args)
{
    int N = 3, K = 2;
  
    // Function call
    System.out.print(sumofGCD(N, K));
}
}
 
// This code is contributed by PrinciRaj1992

蟒蛇3

# Python3 implementation of the above approach
MOD = (int)(1e9 + 7)
 
# Function to find a^b in log(b)
def fastexpo(a, b) :
    res = 1
    a = a % MOD
    while (b > 0) :
        if ((b & 1) != 0) :
            res = (res * a) % MOD
        a = a * a
        a = a % MOD
        b = b >> 1
    return res
 
# Function that finds the sum of GCD
# of all the subsequence of N length
def sumofGCD(n, k) :
     
    # To stores the number of sequences
    # with gcd i
    count = [0] * (k + 1)
 
    # Find contribution of each gcd
    # to happen
    for g in range(k, 0, -1) :
 
        # To count multiples
        count_multiples = k // g
 
        # possible sequences with
        # overcounting
        temp = fastexpo(count_multiples, n)
 
        # to avoid overflow
        temp = temp % MOD
 
        # Find extra element which will
        # not form gcd = i
        extra = 0
 
        # Find overcounting
        for j in range(g * 2, k + 1, g) :
            extra = extra + count[j]
            extra = extra % MOD
 
        # Remove the overcounting
        count[g] = temp - extra + MOD
        count[g] = count[g] % MOD
 
    # To store the final answer
    Sum = 0
    for i in range(1, k + 1) :
        add = count[i] % MOD * i % MOD
        add = add % MOD
        Sum = Sum + add
        Sum = Sum % MOD
 
    # Return Final answer
    return Sum
 
  # Driver code
N, K = 3, 2
 
# Function call
print(sumofGCD(N, K))
 
# This code is contributed by divyeshrabadiya07.

C#

// C# implementation of the above approach
using System;
 
class GFG{
static int MOD = (int)1e9 + 7;
   
// Function to find a^b in log(b)
static int fastexpo(int a, int b)
{
   
    int res = 1;
    a %= MOD;
   
    while (b > 0) {
        if (b % 2 == 1)
            res = (res * a) % MOD;
        a *= a;
        a %= MOD;
        b >>= 1;
    }
    return res;
}
   
// Function that finds the sum of GCD
// of all the subsequence of N length
static int sumofGCD(int n, int k)
{
   
    // To stores the number of sequences
    // with gcd i
    int []count = new int[k + 1];
   
    // Find contribution of each gcd
    // to happen
    for (int g = k; g >= 1; g--) {
   
        // To count multiples
        int count_multiples = k / g;
   
        // possible sequences with
        // overcounting
        int temp;
   
        temp = fastexpo(count_multiples, n);
   
        // to astatic void overflow
        temp %= MOD;
   
        // Find extra element which will
        // not form gcd = i
        int extra = 0;
   
        // Find overcounting
        for (int j = g * 2; j <= k; j += g) {
   
            extra = (extra + count[j]);
            extra %= MOD;
        }
   
        // Remove the overcounting
        count[g] = (temp - extra + MOD);
        count[g] %= MOD;
    }
   
    // To store the readonly answer
    int sum = 0;
    int add;
   
    for (int i = 1; i <= k; ++i) {
   
        add = (count[i] % MOD * i % MOD);
        add %= MOD;
        sum += add;
        sum %= MOD;
    }
   
    // Return Final answer
    return sum;
}
   
// Driver Code
public static void Main(String[] args)
{
    int N = 3, K = 2;
   
    // Function call
    Console.Write(sumofGCD(N, K));
}
}
 
// This code is contributed by Princi Singh

Javascript


输出:
9

时间复杂度: O( K*log(N) + K*log(log(K)) )