Dadas consultas Q do tipo: L R para cada consulta você deve imprimir o número máximo de divisores que um número x (L<= x <= R) tem.
Exemplos:
L = 1 R = 10 : 1 has 1 divisor. 2 has 2 divisors. 3 has 2 divisors. 4 has 3 divisors. 5 has 2 divisors. 6 has 4 divisors. 7 has 2 divisors. 8 has 4 divisors. 9 has 3 divisors. 10 has 4 divisors. So the answer for above query is 4 as it is the maximum number of divisors a number has in [1 10].
Pré-requisitos: Peneira de Eratóstenes Árvore de segmento
Abaixo estão as etapas para resolver o problema.
- Primeiramente vamos ver quantos divisores um número tem n = p1k1*p2k2* ... *pnkn (onde p1p2... p.nsão números primos) tem; a resposta é (k1+ 1)*(k2+ 1)*...*(kn+1) . Como? Para cada número primo na fatoração prima podemos ter seu keu+ 1 potências possíveis em um divisor (0 1 2... keu).
- Agora vamos ver como podemos encontrar a fatoração primária de um número. Primeiro construímos um array menor_prime[] que armazena o menor divisor primo de eu no euo índice dividimos um número pelo seu menor divisor primo para obter um novo número (também temos o menor divisor primo deste novo número armazenado) continuamos fazendo isso até que o menor primo do número mude quando o menor fator primo do novo número for diferente do número anterior, temos keupara o euonúmero primo na fatoração prima do número fornecido.
- Finalmente obtemos o número de divisores para todos os números e os armazenamos em uma árvore de segmentos que mantém os números máximos nos segmentos. Respondemos a cada consulta consultando a árvore de segmentos.
derivada parcial de látexC++
// A C++ implementation of the above idea to process // queries of finding a number with maximum divisors. #include using namespace std; #define maxn 1000005 #define INF 99999999 int smallest_prime[maxn]; int divisors[maxn]; int segmentTree[4 * maxn]; // Finds smallest prime factor of all numbers in // range[1 maxn) and stores them in smallest_prime[] // smallest_prime[i] should contain the smallest prime // that divides i void findSmallestPrimeFactors() { // Initialize the smallest_prime factors of all // to infinity for (int i = 0 ; i < maxn ; i ++ ) smallest_prime[i] = INF; // to be built like eratosthenes sieve for (long long i = 2; i < maxn; i++) { if (smallest_prime[i] == INF) { // prime number will have its smallest_prime // equal to itself smallest_prime[i] = i; for (long long j = i * i; j < maxn; j += i) // if 'i' is the first prime number reaching 'j' if (smallest_prime[j] > i) smallest_prime[j] = i; } } } // number of divisors of n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // are equal to (k1+1) * (k2+1) ... (kn+1) // this function finds the number of divisors of all numbers // in range [1 maxn) and stores it in divisors[] // divisors[i] stores the number of divisors i has void buildDivisorsArray() { for (int i = 1; i < maxn; i++) { divisors[i] = 1; int n = i p = smallest_prime[i] k = 0; // we can obtain the prime factorization of the number n // n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) using the // smallest_prime[] array we keep dividing n by its // smallest_prime until it becomes 1 whilst we check // if we have need to set k zero while (n > 1) { n = n / p; k ++; if (smallest_prime[n] != p) { //use p^k initialize k to 0 divisors[i] = divisors[i] * (k + 1); k = 0; } p = smallest_prime[n]; } } } // builds segment tree for divisors[] array void buildSegtmentTree(int node int a int b) { // leaf node if (a == b) { segmentTree[node] = divisors[a]; return ; } //build left and right subtree buildSegtmentTree(2 * node a (a + b) / 2); buildSegtmentTree(2 * node + 1 ((a + b) / 2) + 1 b); //combine the information from left //and right subtree at current node segmentTree[node] = max(segmentTree[2 * node] segmentTree[2 *node + 1]); } //returns the maximum number of divisors in [l r] int query(int node int a int b int l int r) { // If current node's range is disjoint with query range if (l > b || a > r) return -1; // If the current node stores information for the range // that is completely inside the query range if (a >= l && b <= r) return segmentTree[node]; // Returns maximum number of divisors from left // or right subtree return max(query(2 * node a (a + b) / 2 l r) query(2 * node + 1 ((a + b) / 2) + 1 blr)); } // driver code int main() { // First find smallest prime divisors for all // the numbers findSmallestPrimeFactors(); // Then build the divisors[] array to store // the number of divisors buildDivisorsArray(); // Build segment tree for the divisors[] array buildSegtmentTree(1 1 maxn - 1); cout << 'Maximum divisors that a number has ' << ' in [1 100] are ' << query(1 1 maxn - 1 1 100) << endl; cout << 'Maximum divisors that a number has' << ' in [10 48] are ' << query(1 1 maxn - 1 10 48) << endl; cout << 'Maximum divisors that a number has' << ' in [1 10] are ' << query(1 1 maxn - 1 1 10) << endl; return 0; }
Java // Java implementation of the above idea to process // queries of finding a number with maximum divisors. import java.util.*; class GFG { static int maxn = 10005; static int INF = 999999; static int []smallest_prime = new int[maxn]; static int []divisors = new int[maxn]; static int []segmentTree = new int[4 * maxn]; // Finds smallest prime factor of all numbers // in range[1 maxn) and stores them in // smallest_prime[] smallest_prime[i] should // contain the smallest prime that divides i static void findSmallestPrimeFactors() { // Initialize the smallest_prime factors // of all to infinity for (int i = 0 ; i < maxn ; i ++ ) smallest_prime[i] = INF; // to be built like eratosthenes sieve for (int i = 2; i < maxn; i++) { if (smallest_prime[i] == INF) { // prime number will have its // smallest_prime equal to itself smallest_prime[i] = i; for (int j = i * i; j < maxn; j += i) // if 'i' is the first // prime number reaching 'j' if (smallest_prime[j] > i) smallest_prime[j] = i; } } } // number of divisors of n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // are equal to (k1+1) * (k2+1) ... (kn+1) // this function finds the number of divisors of all numbers // in range [1 maxn) and stores it in divisors[] // divisors[i] stores the number of divisors i has static void buildDivisorsArray() { for (int i = 1; i < maxn; i++) { divisors[i] = 1; int n = i p = smallest_prime[i] k = 0; // we can obtain the prime factorization of // the number n n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // using the smallest_prime[] array we keep dividing n // by its smallest_prime until it becomes 1 // whilst we check if we have need to set k zero while (n > 1) { n = n / p; k ++; if (smallest_prime[n] != p) { // use p^k initialize k to 0 divisors[i] = divisors[i] * (k + 1); k = 0; } p = smallest_prime[n]; } } } // builds segment tree for divisors[] array static void buildSegtmentTree(int node int a int b) { // leaf node if (a == b) { segmentTree[node] = divisors[a]; return ; } //build left and right subtree buildSegtmentTree(2 * node a (a + b) / 2); buildSegtmentTree(2 * node + 1 ((a + b) / 2) + 1 b); //combine the information from left //and right subtree at current node segmentTree[node] = Math.max(segmentTree[2 * node] segmentTree[2 *node + 1]); } // returns the maximum number of divisors in [l r] static int query(int node int a int b int l int r) { // If current node's range is disjoint // with query range if (l > b || a > r) return -1; // If the current node stores information // for the range that is completely inside // the query range if (a >= l && b <= r) return segmentTree[node]; // Returns maximum number of divisors from left // or right subtree return Math.max(query(2 * node a (a + b) / 2 l r) query(2 * node + 1 ((a + b) / 2) + 1 b l r)); } // Driver Code public static void main(String[] args) { // First find smallest prime divisors // for all the numbers findSmallestPrimeFactors(); // Then build the divisors[] array to store // the number of divisors buildDivisorsArray(); // Build segment tree for the divisors[] array buildSegtmentTree(1 1 maxn - 1); System.out.println('Maximum divisors that a number ' + 'has in [1 100] are ' + query(1 1 maxn - 1 1 100)); System.out.println('Maximum divisors that a number ' + 'has in [10 48] are ' + query(1 1 maxn - 1 10 48)); System.out.println('Maximum divisors that a number ' + 'has in [1 10] are ' + query(1 1 maxn - 1 1 10)); } } // This code is contributed by PrinciRaj1992
Python 3 # Python 3 implementation of the above # idea to process queries of finding a # number with maximum divisors. maxn = 1000005 INF = 99999999 smallest_prime = [0] * maxn divisors = [0] * maxn segmentTree = [0] * (4 * maxn) # Finds smallest prime factor of all # numbers in range[1 maxn) and stores # them in smallest_prime[] smallest_prime[i] # should contain the smallest prime that divides i def findSmallestPrimeFactors(): # Initialize the smallest_prime # factors of all to infinity for i in range(maxn ): smallest_prime[i] = INF # to be built like eratosthenes sieve for i in range(2 maxn): if (smallest_prime[i] == INF): # prime number will have its # smallest_prime equal to itself smallest_prime[i] = i for j in range(i * i maxn i): # if 'i' is the first prime # number reaching 'j' if (smallest_prime[j] > i): smallest_prime[j] = i # number of divisors of n = (p1 ^ k1) * # (p2 ^ k2) ... (pn ^ kn) are equal to # (k1+1) * (k2+1) ... (kn+1). This function # finds the number of divisors of all numbers # in range [1 maxn) and stores it in divisors[] # divisors[i] stores the number of divisors i has def buildDivisorsArray(): for i in range(1 maxn): divisors[i] = 1 n = i p = smallest_prime[i] k = 0 # we can obtain the prime factorization # of the number n n = (p1 ^ k1) * (p2 ^ k2) # ... (pn ^ kn) using the smallest_prime[] # array we keep dividing n by its # smallest_prime until it becomes 1 whilst # we check if we have need to set k zero while (n > 1): n = n // p k += 1 if (smallest_prime[n] != p): # use p^k initialize k to 0 divisors[i] = divisors[i] * (k + 1) k = 0 p = smallest_prime[n] # builds segment tree for divisors[] array def buildSegtmentTree( node a b): # leaf node if (a == b): segmentTree[node] = divisors[a] return #build left and right subtree buildSegtmentTree(2 * node a (a + b) // 2) buildSegtmentTree(2 * node + 1 ((a + b) // 2) + 1 b) #combine the information from left #and right subtree at current node segmentTree[node] = max(segmentTree[2 * node] segmentTree[2 * node + 1]) # returns the maximum number of # divisors in [l r] def query(node a b l r): # If current node's range is disjoint # with query range if (l > b or a > r): return -1 # If the current node stores information # for the range that is completely inside # the query range if (a >= l and b <= r): return segmentTree[node] # Returns maximum number of divisors # from left or right subtree return max(query(2 * node a (a + b) // 2 l r) query(2 * node + 1 ((a + b) // 2) + 1 b l r)) # Driver code if __name__ == '__main__': # First find smallest prime divisors # for all the numbers findSmallestPrimeFactors() # Then build the divisors[] array to # store the number of divisors buildDivisorsArray() # Build segment tree for the divisors[] array buildSegtmentTree(1 1 maxn - 1) print('Maximum divisors that a number has ' ' in [1 100] are ' query(1 1 maxn - 1 1 100)) print('Maximum divisors that a number has' ' in [10 48] are ' query(1 1 maxn - 1 10 48)) print( 'Maximum divisors that a number has' ' in [1 10] are ' query(1 1 maxn - 1 1 10)) # This code is contributed by ita_c
C# // C# implementation of the above idea // to process queries of finding a number // with maximum divisors. using System; class GFG { static int maxn = 10005; static int INF = 999999; static int []smallest_prime = new int[maxn]; static int []divisors = new int[maxn]; static int []segmentTree = new int[4 * maxn]; // Finds smallest prime factor of all numbers // in range[1 maxn) and stores them in // smallest_prime[] smallest_prime[i] should // contain the smallest prime that divides i static void findSmallestPrimeFactors() { // Initialize the smallest_prime // factors of all to infinity for (int i = 0 ; i < maxn ; i ++ ) smallest_prime[i] = INF; // to be built like eratosthenes sieve for (int i = 2; i < maxn; i++) { if (smallest_prime[i] == INF) { // prime number will have its // smallest_prime equal to itself smallest_prime[i] = i; for (int j = i * i; j < maxn; j += i) // if 'i' is the first // prime number reaching 'j' if (smallest_prime[j] > i) smallest_prime[j] = i; } } } // number of divisors of // n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // are equal to (k1+1) * (k2+1) ... (kn+1) // this function finds the number of divisors // of all numbers in range [1 maxn) and stores // it in divisors[] divisors[i] stores the // number of divisors i has static void buildDivisorsArray() { for (int i = 1; i < maxn; i++) { divisors[i] = 1; int n = i p = smallest_prime[i] k = 0; // we can obtain the prime factorization of // the number n // n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // using the smallest_prime[] array // we keep dividing n by its smallest_prime // until it becomes 1 whilst we check if // we have need to set k zero while (n > 1) { n = n / p; k ++; if (smallest_prime[n] != p) { // use p^k initialize k to 0 divisors[i] = divisors[i] * (k + 1); k = 0; } p = smallest_prime[n]; } } } // builds segment tree for divisors[] array static void buildSegtmentTree(int node int a int b) { // leaf node if (a == b) { segmentTree[node] = divisors[a]; return; } //build left and right subtree buildSegtmentTree(2 * node a (a + b) / 2); buildSegtmentTree(2 * node + 1 ((a + b) / 2) + 1 b); //combine the information from left //and right subtree at current node segmentTree[node] = Math.Max(segmentTree[2 * node] segmentTree[2 *node + 1]); } // returns the maximum number of divisors in [l r] static int query(int node int a int b int l int r) { // If current node's range is disjoint // with query range if (l > b || a > r) return -1; // If the current node stores information // for the range that is completely inside // the query range if (a >= l && b <= r) return segmentTree[node]; // Returns maximum number of divisors from left // or right subtree return Math.Max(query(2 * node a (a + b) / 2 l r) query(2 * node + 1 ((a + b) / 2) + 1 b l r)); } // Driver Code public static void Main(String[] args) { // First find smallest prime divisors // for all the numbers findSmallestPrimeFactors(); // Then build the divisors[] array // to store the number of divisors buildDivisorsArray(); // Build segment tree for the divisors[] array buildSegtmentTree(1 1 maxn - 1); Console.WriteLine('Maximum divisors that a number ' + 'has in [1 100] are ' + query(1 1 maxn - 1 1 100)); Console.WriteLine('Maximum divisors that a number ' + 'has in [10 48] are ' + query(1 1 maxn - 1 10 48)); Console.WriteLine('Maximum divisors that a number ' + 'has in [1 10] are ' + query(1 1 maxn - 1 1 10)); } } // This code is contributed by 29AjayKumar
JavaScript <script> // JavaScript implementation of the above idea to process // queries of finding a number with maximum divisors. let maxn = 10005; let INF = 999999; let smallest_prime = new Array(maxn); for(let i=0;i<maxn;i++) { smallest_prime[i]=0; } let divisors = new Array(maxn); for(let i=0;i<maxn;i++) { divisors[i]=0; } let segmentTree = new Array(4 * maxn); for(let i=0;i<4*maxn;i++) { segmentTree[i]=0; } // Finds smallest prime factor of all numbers // in range[1 maxn) and stores them in // smallest_prime[] smallest_prime[i] should // contain the smallest prime that divides i function findSmallestPrimeFactors() { // Initialize the smallest_prime factors // of all to infinity for (let i = 0 ; i < maxn ; i ++ ) smallest_prime[i] = INF; // to be built like eratosthenes sieve for (let i = 2; i < maxn; i++) { if (smallest_prime[i] == INF) { // prime number will have its // smallest_prime equal to itself smallest_prime[i] = i; for (let j = i * i; j < maxn; j += i) { // if 'i' is the first // prime number reaching 'j' if (smallest_prime[j] > i) smallest_prime[j] = i; } } } } // number of divisors of n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // are equal to (k1+1) * (k2+1) ... (kn+1) // this function finds the number of divisors of all numbers // in range [1 maxn) and stores it in divisors[] // divisors[i] stores the number of divisors i has function buildDivisorsArray() { for (let i = 1; i < maxn; i++) { divisors[i] = 1; let n = i; let p = smallest_prime[i] let k = 0; // we can obtain the prime factorization of // the number n n = (p1 ^ k1) * (p2 ^ k2) ... (pn ^ kn) // using the smallest_prime[] array we keep dividing n // by its smallest_prime until it becomes 1 // whilst we check if we have need to set k zero while (n > 1) { n = Math.floor(n / p); k++; if (smallest_prime[n] != p) { // use p^k initialize k to 0 divisors[i] = divisors[i] * (k + 1); k = 0; } p = smallest_prime[n]; } } } // builds segment tree for divisors[] array function buildSegtmentTree(nodeab) { // leaf node if (a == b) { segmentTree[node] = divisors[a]; return ; } //build left and right subtree buildSegtmentTree(2 * node a Math.floor((a + b) / 2)); buildSegtmentTree((2 * node) + 1 Math.floor((a + b) / 2) + 1 b); //combine the information from left //and right subtree at current node segmentTree[node] = Math.max(segmentTree[2 * node] segmentTree[(2 *node) + 1]); } // returns the maximum number of divisors in [l r] function query(nodeablr) { // If current node's range is disjoint // with query range if (l > b || a > r) return -1; // If the current node stores information // for the range that is completely inside // the query range if (a >= l && b <= r) return segmentTree[node]; // Returns maximum number of divisors from left // or right subtree return Math.max(query(2 * node a Math.floor((a + b) / 2) l r) query(2 * node + 1 Math.floor((a + b) / 2) + 1 b l r)); } // Driver Code // First find smallest prime divisors // for all the numbers findSmallestPrimeFactors(); // Then build the divisors[] array to store // the number of divisors buildDivisorsArray(); // Build segment tree for the divisors[] array buildSegtmentTree(1 1 maxn - 1); document.write('Maximum divisors that a number ' + 'has in [1 100] are ' + query(1 1 maxn - 1 1 100)+'
'); document.write('Maximum divisors that a number ' + 'has in [10 48] are ' + query(1 1 maxn - 1 10 48)+'
'); document.write('Maximum divisors that a number ' + 'has in [1 10] are ' + query(1 1 maxn - 1 1 10)+'
'); // This code is contributed by avanitrachhadiya2155 </script>
Saída:
java booleano
Maximum divisors that a number has in [1 100] are 12 Maximum divisors that a number has in [10 48] are 10 Maximum divisors that a number has in [1 10] are 4
Complexidade de tempo: O((máxn + Q) * log(máxn))
- Para peneira: O(maxn * log(log(maxn)) )
- Para calcular divisores de cada número: Tudo bem1 + k2 + ... + kn) < O(log(máxn))
- Para consultar cada intervalo: O(log(máxn))
Espaço Auxiliar: Sobre)
Tópico Relacionado: