Dada una array arr[] , la tarea es encontrar el recuento de sub-arrays con GCD igual a 1 .
Ejemplos:
Entrada: arr[] = {1, 1, 1}
Salida: 6
Cada subarreglo del arreglo dado tiene GCD
de 1 y hay un total de 6 subarreglos.
Entrada: arr[] = {2, 2, 2}
Salida: 0
Enfoque: este problema se puede resolver en O (NlogN) utilizando una estructura de datos de árbol de segmentos . El segmento que se construirá se puede usar para responder consultas de rango-gcd.
Entendamos el algoritmo ahora. Utilice la técnica de dos puntos para resolver este problema. Hagamos algunas observaciones antes de discutir el algoritmo.
- Digamos que G es el GCD del subarreglo arr[l…r] y G1 es el GCD del subarreglo arr[l+1…r] . G menor o igual a G1 siempre.
- Digamos que para el L1 dado , R1 es el primer índice tal que GCD del rango [L, R] es 1 , entonces para cualquier L2 mayor o igual que L1 , R2 también será mayor o igual que R1 .
Después de la observación anterior, la técnica de dos punteros tiene perfecto sentido, es decir, si se conoce la longitud
de la R más pequeña para un índice L y luego para un índice L + 1 , la búsqueda debe comenzar desde R en adelante.
A continuación se muestra la implementación del enfoque anterior:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define maxLen 30 // Array to store segment-tree int seg[3 * maxLen]; // Function to build segment-tree to // answer range GCD queries int build(int l, int r, int in, int* arr) { // Base-case if (l == r) return seg[in] = arr[l]; // Mid element of the range int mid = (l + r) / 2; // Merging the result of left and right sub-tree return seg[in] = __gcd(build(l, mid, 2 * in + 1, arr), build(mid + 1, r, 2 * in + 2, arr)); } // Function to perform range GCD queries int query(int l, int r, int l1, int r1, int in) { // Base-cases if (l1 <= l and r <= r1) return seg[in]; if (l > r1 or r < l1) return 0; // Mid-element int mid = (l + r) / 2; // Calling left and right child return __gcd(query(l, mid, l1, r1, 2 * in + 1), query(mid + 1, r, l1, r1, 2 * in + 2)); } // Function to find the required count int findCnt(int* arr, int n) { // Building the segment tree build(0, n - 1, 0, arr); // Two pointer variables int i = 0, j = 0; // To store the final answer int ans = 0; // Looping while (i < n) { // Incrementing j till we don't get // a gcd value of 1 while (j < n and query(0, n - 1, i, j, 0) != 1) j++; // Updating the final answer ans += (n - j); // Increment i i++; // Update j j = max(j, i); } // Returning the final answer return ans; } // Driver code int main() { int arr[] = { 1, 1, 1, 1 }; int n = sizeof(arr) / sizeof(int); cout << findCnt(arr, n); return 0; }
Java
// Java implementation of the above approach class GFG { static int maxLen = 30; // Array to store segment-tree static int []seg = new int[3 * maxLen]; // Function to build segment-tree to // answer range GCD queries static int build(int l, int r, int in, int[] arr) { // Base-case if (l == r) return seg[in] = arr[l]; // Mid element of the range int mid = (l + r) / 2; // Merging the result of left and right sub-tree return seg[in] = __gcd(build(l, mid, 2 * in + 1, arr), build(mid + 1, r, 2 * in + 2, arr)); } // Function to perform range GCD queries static int query(int l, int r, int l1, int r1, int in) { // Base-cases if (l1 <= l && r <= r1) return seg[in]; if (l > r1 || r < l1) return 0; // Mid-element int mid = (l + r) / 2; // Calling left and right child return __gcd(query(l, mid, l1, r1, 2 * in + 1), query(mid + 1, r, l1, r1, 2 * in + 2)); } // Function to find the required count static int findCnt(int[] arr, int n) { // Building the segment tree build(0, n - 1, 0, arr); // Two pointer variables int i = 0, j = 0; // To store the final answer int ans = 0; // Looping while (i < n) { // Incrementing j till we don't get // a gcd value of 1 while (j < n && query(0, n - 1, i, j, 0) != 1) j++; // Updating the final answer ans += (n - j); // Increment i i++; // Update j j = Math.max(j, i); } // Returning the final answer return ans; } static int __gcd(int a, int b) { return b == 0 ? a : __gcd(b, a % b); } // Driver code public static void main(String []args) { int arr[] = { 1, 1, 1, 1 }; int n = arr.length; System.out.println(findCnt(arr, n)); } } // This code is contributed by PrinciRaj1992
Python3
# Python3 implementation of the above approach from math import gcd maxLen = 30; # Array to store segment-tree seg = [0] * (3 * maxLen); # Function to build segment-tree to # answer range GCD queries def build(l, r, i, arr) : # Base-case if (l == r) : seg[i] = arr[l]; return seg[i]; # Mid element of the range mid = (l + r) // 2; # Merging the result of left and right sub-tree seg[i] = gcd(build(l, mid, 2 * i + 1, arr), build(mid + 1, r, 2 * i + 2, arr)); return seg[i]; # Function to perform range GCD queries def query(l, r, l1, r1, i) : # Base-cases if (l1 <= l and r <= r1) : return seg[i]; if (l > r1 or r < l1) : return 0; # Mid-element mid = (l + r) // 2; # Calling left and right child return gcd(query(l, mid, l1, r1, 2 * i + 1), query(mid + 1, r, l1, r1, 2 * i + 2)); # Function to find the required count def findCnt(arr, n) : # Building the segment tree build(0, n - 1, 0, arr); # Two pointer variables i = 0; j = 0; # To store the final answer ans = 0; # Looping while (i < n) : # Incrementing j till we don't get # a gcd value of 1 while (j < n and query(0, n - 1, i, j, 0) != 1) : j += 1; # Updating the final answer ans += (n - j); # Increment i i += 1; # Update j j = max(j, i); # Returning the final answer return ans; # Driver code if __name__ == "__main__" : arr = [ 1, 1, 1, 1 ]; n = len(arr); print(findCnt(arr, n)); # This code is contributed by AnkitRai01
C#
// C# implementation of the above approach using System; class GFG { static int maxLen = 30; // Array to store segment-tree static int []seg = new int[3 * maxLen]; // Function to build segment-tree to // answer range GCD queries static int build(int l, int r, int iN, int[] arr) { // Base-case if (l == r) return seg[iN] = arr[l]; // Mid element of the range int mid = (l + r) / 2; // Merging the result of left and right sub-tree return seg[iN] = __gcd(build(l, mid, 2 * iN + 1, arr), build(mid + 1, r, 2 * iN + 2, arr)); } // Function to perform range GCD queries static int query(int l, int r, int l1, int r1, int iN) { // Base-cases if (l1 <= l && r <= r1) return seg[iN]; if (l > r1 || r < l1) return 0; // Mid-element int mid = (l + r) / 2; // Calling left and right child return __gcd(query(l, mid, l1, r1, 2 * iN + 1), query(mid + 1, r, l1, r1, 2 * iN + 2)); } // Function to find the required count static int findCnt(int[] arr, int n) { // Building the segment tree build(0, n - 1, 0, arr); // Two pointer variables int i = 0, j = 0; // To store the final answer int ans = 0; // Looping while (i < n) { // Incrementing j till we don't get // a gcd value of 1 while (j < n && query(0, n - 1, i, j, 0) != 1) j++; // Updating the final answer ans += (n - j); // Increment i i++; // Update j j = Math.Max(j, i); } // Returning the final answer return ans; } static int __gcd(int a, int b) { return b == 0 ? a : __gcd(b, a % b); } // Driver code public static void Main(String []args) { int []arr = { 1, 1, 1, 1 }; int n = arr.Length; Console.WriteLine(findCnt(arr, n)); } } // This code is contributed by PrinciRaj1992
Javascript
<script> // Javascript implementation of the above approach let maxLen = 30; // Array to store segment-tree let seg = new Array(3 * maxLen); // Function to build segment-tree to // answer range GCD queries function build(l, r, inn, arr) { // Base-case if (l == r) return seg[inn] = arr[l]; // Mid element of the range let mid = Math.floor((l + r) / 2); // Merging the result of left and right sub-tree return seg[inn] = __gcd(build(l, mid, 2 * inn + 1, arr), build(mid + 1, r, 2 * inn + 2, arr)); } // Function to perform range GCD queries function query(l, r, l1, r1, inn) { // Base-cases if (l1 <= l && r <= r1) return seg[inn]; if (l > r1 || r < l1) return 0; // Mid-element let mid = Math.floor((l + r) / 2); // Calling left and right child return __gcd(query(l, mid, l1, r1, 2 * inn + 1), query(mid + 1, r, l1, r1, 2 * inn + 2)); } // Function to find the required count function findCnt(arr, n) { // Building the segment tree build(0, n - 1, 0, arr); // Two pointer variables let i = 0, j = 0; // To store the final answer let ans = 0; // Looping while (i < n) { // Incrementing j till we don't get // a gcd value of 1 while (j < n && query(0, n - 1, i, j, 0) != 1) j++; // Updating the final answer ans += (n - j); // Increment i i++; // Update j j = Math.max(j, i); } // Returning the final answer return ans; } function __gcd(a, b) { return b == 0 ? a : __gcd(b, a % b); } // Driver code let arr = [1, 1, 1, 1]; let n = arr.length; document.write(findCnt(arr, n)); // This code is contributed by gfgking </script>
10
Publicación traducida automáticamente
Artículo escrito por DivyanshuShekhar1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA