计算在L-R范围内除以所有数字的元素

给定N个数字和Q个查询,每个查询都由L和R组成。任务是编写一个程序,打印数字计数,将给定范围L-R内的所有数字除以。 例如:

null
Input : a = {3, 4, 2, 2, 4, 6}         Q = 2        L = 1 R = 4          L = 2 R = 6    Output :  0          2 Explanation : The range 1-4 has {3, 4, 2, 2} which does not have any number that divides all the numbers in this range. The range 2-6 has {4, 2, 2, 4, 6} which has  2 numbers {2, 2} which divides all numbers in the given range. Input: a = {1, 2, 3, 5}        Q = 2        L = 1 R = 4        L = 2 R = 4 Output: 1         0      

天真的方法: 对每个查询从范围L-R进行迭代,并检查索引i处的给定元素是否除以范围内的所有数字。我们计算所有除以这些数的元素的个数。在最坏的情况下,每个查询的复杂性都将是 O(n) 2. ) . 下面是Naive方法的实现:

C++

// CPP program to Count elements which
// divides all numbers in range L-R
#include <bits/stdc++.h>
using namespace std;
// function to count element
// Time complexity O(n^2) worst case
int answerQuery( int a[], int n,
int l, int r)
{
// answer for query
int count = 0;
// 0 based index
l = l - 1;
// iterate for all elements
for ( int i = l; i < r; i++)
{
int element = a[i];
int divisors = 0;
// check if the element divides
// all numbers in range
for ( int j = l; j < r; j++)
{
// no of elements
if (a[j] % a[i] == 0)
divisors++;
else
break ;
}
// if all elements are divisible by a[i]
if (divisors == (r - l))
count++;
}
// answer for every query
return count;
}
// Driver Code
int main()
{
int a[] = { 1, 2, 3, 5 };
int n = sizeof (a) / sizeof (a[0]);
int l = 1, r = 4;
cout << answerQuery(a, n, l, r) << endl;
l = 2, r = 4;
cout << answerQuery(a, n, l, r) << endl;
return 0;
}


JAVA

// Java program to Count elements which
// divides all numbers in range L-R
import java.io.*;
class GFG
{
// function to count element
// Time complexity O(n^2) worst case
static int answerQuery( int a[], int n,
int l, int r)
{
// answer for query
int count = 0 ;
// 0 based index
l = l - 1 ;
// iterate for all elements
for ( int i = l; i < r; i++)
{
int element = a[i];
int divisors = 0 ;
// check if the element divides
// all numbers in range
for ( int j = l; j < r; j++)
{
// no of elements
if (a[j] % a[i] == 0 )
divisors++;
else
break ;
}
// if all elements are divisible by a[i]
if (divisors == (r - l))
count++;
}
// answer for every query
return count;
}
// Driver Code
public static void main (String[] args)
{
int a[] = { 1 , 2 , 3 , 5 };
int n = a.length;
int l = 1 , r = 4 ;
System.out.println( answerQuery(a, n, l, r));
l = 2 ; r = 4 ;
System.out.println( answerQuery(a, n, l, r));
}
}
// This code is contributed by anuj_67..


Python3

# Python 3 program to Count elements which
# divides all numbers in range L-R
# function to count element
# Time complexity O(n^2) worst case
def answerQuery(a, n, l, r):
# answer for query
count = 0
# 0 based index
l = l - 1
# iterate for all elements
for i in range (l, r, 1 ):
element = a[i]
divisors = 0
# check if the element divides
# all numbers in range
for j in range (l, r, 1 ):
# no of elements
if (a[j] % a[i] = = 0 ):
divisors + = 1
else :
break
# if all elements are divisible
# by a[i]
if (divisors = = (r - l)):
count + = 1
# answer for every query
return count
# Driver Code
if __name__ = = '__main__' :
a = [ 1 , 2 , 3 , 5 ]
n = len (a)
l = 1
r = 4
print (answerQuery(a, n, l, r))
l = 2
r = 4
print (answerQuery(a, n, l, r))
# This code is contributed by
# Shashank_Sharma


C#

// C# program to Count elements which
// divides all numbers in range L-R
using System;
class GFG
{
// function to count element
// Time complexity O(n^2) worst case
static int answerQuery( int []a, int n,
int l, int r)
{
// answer for query
int count = 0 ;
// 0 based index
l = l - 1 ;
// iterate for all elements
for ( int i = l; i < r; i++)
{
//int element = a[i];
int divisors = 0 ;
// check if the element divides
// all numbers in range
for ( int j = l; j < r; j++)
{
// no of elements
if (a[j] % a[i] == 0 )
divisors++;
else
break ;
}
// if all elements are divisible by a[i]
if (divisors == (r - l))
count++;
}
// answer for every query
return count;
}
// Driver Code
public static void Main ()
{
int []a = { 1 , 2 , 3 , 5 };
int n = a.Length;
int l = 1 , r = 4 ;
Console.WriteLine(answerQuery(a, n, l, r));
l = 2 ; r = 4 ;
Console.WriteLine(answerQuery(a, n, l, r));
}
}
// This code is contributed by anuj_67..


PHP

<?php
// PHP program to Count elements which
// divides all numbers in range L-R
// function to count element
// Time complexity O(n^2) worst case
function answerQuery( $a , $n , $l , $r )
{
// answer for query
$count = 0;
// 0 based index
$l = $l - 1;
// iterate for all elements
for ( $i = $l ; $i < $r ; $i ++)
{
$element = $a [ $i ];
$divisors = 0;
// check if the element divides
// all numbers in range
for ( $j = $l ; $j < $r ; $j ++)
{
// no of elements
if ( $a [ $j ] % $a [ $i ] == 0)
$divisors ++;
else
break ;
}
// if all elements are divisible by a[i]
if ( $divisors == ( $r - $l ))
$count ++;
}
// answer for every query
return $count ;
}
// Driver Code
$a = array (1, 2, 3, 5);
$n = sizeof( $a );
$l = 1; $r = 4;
echo answerQuery( $a , $n , $l , $r ) . "" ;
$l = 2; $r = 4;
echo answerQuery( $a , $n , $l , $r ) . "" ;
// This code is contributed
// by Akanksha Rai


Javascript

<script>
// javascript program to Count elements which
// divides all numbers in range L-R
// function to count element
// Time complexity O(n^2) worst case
function answerQuery(a , n , l , r)
{
// answer for query
var count = 0;
// 0 based index
l = l - 1;
// iterate for all elements
for (i = l; i < r; i++) {
var element = a[i];
var divisors = 0;
// check if the element divides
// all numbers in range
for (j = l; j < r; j++) {
// no of elements
if (a[j] % a[i] == 0)
divisors++;
else
break ;
}
// if all elements are divisible by a[i]
if (divisors == (r - l))
count++;
}
// answer for every query
return count;
}
// Driver Code
var a = [ 1, 2, 3, 5 ];
var n = a.length;
var l = 1, r = 4;
document.write(answerQuery(a, n, l, r)+ "<br/>" );
l = 2;
r = 4;
document.write(answerQuery(a, n, l, r));
// This code is contributed by gauravrajput1
</script>


输出:

10

有效方法: 使用 分段树 来解决这个问题。如果一个元素将给定范围内的所有数字相除,那么该元素是该范围内的最小数,它是给定范围L-R内所有元素的gcd。因此,如果最小值等于该范围内的gcd,那么L-R范围内的最小数目的计数将是我们对每个查询的答案。问题归根结底在于找到正确的答案 GCD , 最低限度 计数最小值 对于每个范围,使用分段树。在树的每个节点上,存储三个值。 在查询给定范围时,如果给定范围的gcd和最小值相等, 计数最小值 作为答案返回。如果它们不相等,则返回0作为答案。 以下是高效方法的实施:

CPP

// CPP program to Count elements
// which divides all numbers in
// range L-R efficient approach
#include <bits/stdc++.h>
using namespace std;
#define N 100005
// predefines the tree with nodes
// storing gcd, min and count
struct node
{
int gcd;
int min;
int cnt;
} tree[5 * N];
// function to construct the tree
void buildtree( int low, int high,
int pos, int a[])
{
// base condition
if (low == high)
{
// initially always gcd and min
// are same at leaf node
tree[pos].min =  tree[pos].gcd = a[low];
tree[pos].cnt = 1;
return ;
}
int mid = (low + high) >> 1;
// left-subtree
buildtree(low, mid, 2 * pos + 1, a);
// right-subtree
buildtree(mid + 1, high, 2 * pos + 2, a);
// finds gcd of left and right subtree
tree[pos].gcd = __gcd(tree[2 * pos + 1].gcd,
tree[2 * pos + 2].gcd);
// left subtree has the minimum element
if (tree[2 * pos + 1].min < tree[2 * pos + 2].min)
{
tree[pos].min = tree[2 * pos + 1].min;
tree[pos].cnt = tree[2 * pos + 1].cnt;
}
// right subtree has the minimum element
else
if (tree[2 * pos + 1].min > tree[2 * pos + 2].min)
{
tree[pos].min = tree[2 * pos + 2].min;
tree[pos].cnt = tree[2 * pos + 2].cnt;
}
// both subtree has the same minimum element
else
{
tree[pos].min = tree[2 * pos + 1].min;
tree[pos].cnt = tree[2 * pos + 1].cnt +
tree[2 * pos + 2].cnt;
}
}
// function that answers every query
node query( int s, int e, int low, int high, int pos)
{
node dummy;
// out of range
if (e < low or s > high)
{
dummy.gcd = dummy.min = dummy.cnt = 0;
return dummy;
}
// in range
if (s >= low and e <= high)
{
node dummy;
dummy.gcd = tree[pos].gcd;
dummy.min = tree[pos].min;
if (dummy.gcd != dummy.min)
dummy.cnt = 0;
else
dummy.cnt = tree[pos].cnt;
return dummy;
}
int mid = (s + e) >> 1;
// left-subtree
node ans1 = query(s, mid, low,
high, 2 * pos + 1);
// right-subtree
node ans2 = query(mid + 1, e, low,
high, 2 * pos + 2);
node ans;
// when both left subtree and
// right subtree is in range
if (ans1.gcd and ans2.gcd)
{
// merge two trees
ans.gcd = __gcd(ans1.gcd, ans2.gcd);
ans.min = min(ans1.min, ans2.min);
// when gcd is not equal to min
if (ans.gcd != ans.min)
ans.cnt = 0;
else
{
// add count when min is
// same of both subtree
if (ans1.min == ans2.min)
ans.cnt = ans2.cnt + ans1.cnt;
// store the minimal's count
else
if (ans1.min < ans2.min)
ans.cnt = ans1.cnt;
else
ans.cnt = ans2.cnt;
}
return ans;
}
// only left subtree is in range
else if (ans1.gcd)
return ans1;
// only right subtree is in range
else if (ans2.gcd)
return ans2;
}
// function to answer query in range l-r
int answerQuery( int a[], int n, int l, int r)
{
// calls the function which returns
// a node this function returns the
// count which will be the answer
return query(0, n - 1, l - 1, r - 1, 0).cnt;
}
// Driver Code
int main()
{
int a[] = { 3, 4, 2, 2, 4, 6 };
int n = sizeof (a) / sizeof (a[0]);
buildtree(0, n - 1, 0, a);
int l = 1, r = 4;
// answers 1-st query
cout << answerQuery(a, n, l, r) << endl;
l = 2, r = 6;
// answers 2nd query
cout << answerQuery(a, n, l, r) << endl;
return 0;
}


输出:

02

时间复杂性: 树构造的时间复杂度是 O(n logn) 因为树的构造需要O(n),而找出gcd需要O(logn)。在最坏的情况下,每个查询所需的时间将是 O(logn*logn),因为内置函数u gcd取O(logn)

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享