📌  相关文章
📜  从给定数组中查找所有元素都可被K整除的最长前缀的长度的查询

📅  最后修改于: 2021-04-22 03:19:17             🧑  作者: Mango

给定一个包含N个元素的数组arr []和一个Q []数组,每个查询的任务是找到最长前缀的长度,以使该前缀的所有元素都可以被K整除。

例子:

方法:想法是观察到,如果数组的前i个元素可以被给定的整数K整除,那么它们的GCD也可以被K整除。请按照以下步骤解决问题:

  1. 在找到每个查询的答案之前,请预先计算另一个数组g []中数组前缀的gcd,以使g [0] = arr [0] ,而其余元素g [i] = GCD(arr [i],g [i – 1])
  2. 然后,对于在阵列每个元素[],在阵列克[]执行二进制搜索,找到的最后一个索引[]其是由Q [I]整除。
  3. 必须注意的是,该索引之前的所有元素都可以被K整除,因为直到该索引为止的所有元素的gcd都可以被K整除。
  4. 打印最长前缀的长度。

下面是上述方法的实现。

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find index of the last
// element which is divisible the given element
int binSearch(int* g, int st, int en, int val)
{
    // Initially assume the
    // index to be -1
    int ind = -1;
    while (st <= en) {
 
        // Find the mid element
        // of the subarray
        int mid = st + (en - st) / 2;
 
        // If the mid element is divisible by
        // given element, then move to right
        // of mid and update ind to mid
        if (g[mid] % val == 0) {
            ind = mid;
            st = mid + 1;
        }
 
        // Otherwise, move to left of mid
        else {
            en = mid - 1;
        }
    }
 
    // Return the length of prefix
    return ind + 1;
}
 
// Function to compute and print for each query
void solveQueries(int* arr, int* queries,
                  int n, int q)
{
    int g[n];
 
    // Pre compute the gcd of the prefixes
    // of the input array in the array g[]
    for (int i = 0; i < n; i++) {
        if (i == 0) {
            g[i] = arr[i];
        }
        else {
            g[i] = __gcd(g[i - 1], arr[i]);
        }
    }
 
    // Perform binary search
    // for each query
    for (int i = 0; i < q; i++) {
        cout << binSearch(g, 0, n - 1,
                          queries[i])
             << " ";
    }
}
 
// Driver Code
int main()
{
    // Given array
    int arr[] = { 12, 6, 15, 3, 10 };
 
    // Size of array
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Given Queries
    int queries[] = { 4, 3, 2 };
 
    // Size of queries
    int q = sizeof(queries) / sizeof(queries[0]);
 
    solveQueries(arr, queries, n, q);
}


Java
// Java program for the above approach
import java.util.*;
class GFG
{
 
// Function to find index of the last
// element which is divisible the given element
static int binSearch(int[] g, int st, int en, int val)
{
   
    // Initially assume the
    // index to be -1
    int ind = -1;
    while (st <= en)
    {
 
        // Find the mid element
        // of the subarray
        int mid = st + (en - st) / 2;
 
        // If the mid element is divisible by
        // given element, then move to right
        // of mid and update ind to mid
        if (g[mid] % val == 0)
        {
            ind = mid;
            st = mid + 1;
        }
 
        // Otherwise, move to left of mid
        else
        {
            en = mid - 1;
        }
    }
 
    // Return the length of prefix
    return ind + 1;
}
 
// Function to compute and print for each query
static void solveQueries(int []arr, int []queries,
                  int n, int q)
{
    int []g = new int[n];
 
    // Pre compute the gcd of the prefixes
    // of the input array in the array g[]
    for (int i = 0; i < n; i++)
    {
        if (i == 0) {
            g[i] = arr[i];
        }
        else {
            g[i] = __gcd(g[i - 1], arr[i]);
        }
    }
 
    // Perform binary search
    // for each query
    for (int i = 0; i < q; i++)
    {
        System.out.print(binSearch(g, 0, n - 1,
                          queries[i])
            + " ");
    }
}
static int __gcd(int a, int b) 
{ 
    return b == 0? a:__gcd(b, a % b);    
}
   
// Driver Code
public static void main(String[] args)
{
   
    // Given array
    int arr[] = { 12, 6, 15, 3, 10 };
 
    // Size of array
    int n = arr.length;
 
    // Given Queries
    int queries[] = { 4, 3, 2 };
 
    // Size of queries
    int q = queries.length;
    solveQueries(arr, queries, n, q);
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program for the above approach
from math import gcd as __gcd
 
# Function to find index of the last
# element which is divisible the
# given element
def binSearch(g, st, en, val):
     
    # Initially assume the
    # index to be -1
    ind = -1
     
    while (st <= en):
 
        # Find the mid element
        # of the subarray
        mid = st + (en - st) // 2
 
        # If the mid element is divisible by
        # given element, then move to right
        # of mid and update ind to mid
        if (g[mid] % val == 0):
            ind = mid
            st = mid + 1
 
        # Otherwise, move to left of mid
        else:
            en = mid - 1
 
    # Return the length of prefix
    return ind + 1
 
# Function to compute and prfor each query
def solveQueries(arr, queries, n, q):
     
    g = [0 for i in range(n)]
 
    # Pre compute the gcd of the prefixes
    # of the input array in the array g[]
    for i in range(n):
        if (i == 0):
            g[i] = arr[i]
        else:
            g[i] = __gcd(g[i - 1], arr[i])
 
    # Perform binary search
    # for each query
    for i in range(q):
        print(binSearch(g, 0, n - 1,
                        queries[i]), end = " ")
 
# Driver Code
if __name__ == '__main__':
     
    # Given array
    arr = [ 12, 6, 15, 3, 10 ]
 
    # Size of array
    n = len(arr)
 
    # Given Queries
    queries = [ 4, 3, 2 ]
 
    # Size of queries
    q = len(queries)
 
    solveQueries(arr, queries, n, q)
 
# This code is contributed by mohit kumar 29


C#
// C# program to implement
// the above approach 
using System;
class GFG
{
  
// Function to find index of the last
// element which is divisible the given element
static int binSearch(int[] g, int st, int en, int val)
{
   
  // Initially assume the
  // index to be -1
  int ind = -1;
  while (st <= en)
  {
 
    // Find the mid element
    // of the subarray
    int mid = st + (en - st) / 2;
 
    // If the mid element is divisible by
    // given element, then move to right
    // of mid and update ind to mid
    if (g[mid] % val == 0)
    {
      ind = mid;
      st = mid + 1;
    }
 
    // Otherwise, move to left of mid
    else
    {
      en = mid - 1;
    }
  }
 
  // Return the length of prefix
  return ind + 1;
}
 
  // Recursive function to return
  // gcd of a and b
  static int gcd(int a, int b)
  {
 
    // Everything divides 0
    if (a == 0)
      return b;
    if (b == 0)
      return a;
 
    // base case
    if (a == b)
      return a;
 
    // a is greater
    if (a > b)
      return gcd(a - b, b);
 
    return gcd(a, b - a);
  }
 
  // Function to compute and print for each query
  static void solveQueries(int[] arr, int[] queries,
                           int n, int q)
  {
    int[] g = new int[n];
 
    // Pre compute the gcd of the prefixes
    // of the input array in the array g[]
    for (int i = 0; i < n; i++)
    {
      if (i == 0)
      {
        g[i] = arr[i];
      }
      else
      {
        g[i] = gcd(g[i - 1], arr[i]);
      }
    }
 
    // Perform binary search
    // for each query
    for (int i = 0; i < q; i++)
    {
      Console.Write(binSearch(g, 0, n - 1,
                              queries[i]) + " ");
    }
  }
  
// Driver code
public static void Main()
{
   
    // Given array
    int[] arr = { 12, 6, 15, 3, 10 };
  
    // Size of array
    int n = arr.Length;
  
    // Given Queries
    int[] queries = { 4, 3, 2 };
  
    // Size of queries
    int q = queries.Length;
    solveQueries(arr, queries, n, q);
}
}
 
// This code is contributed by susmitakundugoaldanga


输出:
1 4 2

时间复杂度: O(NlogN + QlogN)
辅助空间: O(N)