Given an array arr[] of line segments on the x-axis and an integer K, the task is to calculate the number of ways to choose the K line-segments such that they do intersect at any point. Since the answer can be large, print it to modulo 10^9+7.
Examples:
Input: arr[] = [[1, 3], [4, 5], [5, 7]], K = 2
Output: 2
Explanation:
The first way to choose [1, 3], [4, 5] and the second way is [1, 3], [5, 7].Since Intersection of [4, 5], [5, 7] is not zero and hence cannot be included in answer.Input: [[3, 7], [1, 4], [6, 9], [8, 13], [9, 11]], K = 1
Output: 0
Explanation:
Since we are only looking for single line segment, but for every single line segment Intersection is always non empty.
Approach:
To solve the problem mentioned above we will try to find out the number of odd cases means those cases whose intersection is non-empty. So clearly our answer will be Total Case – Odd Case.
To compute the total number of cases, the below approach is followed:
- Total cases that are possible are “n choose k” or nCk
- We pre-calculate the inverse and factorial of required numbers to calculate nCk
- in O(1) time
- The K line-segment intersect as if min(R1, R2, .., R{k-1}) >= Li where line-segment [Li, Ri] is under consideration. Maintain a multiset, to maintain order. Firstly, sort the segments in increasing order of Li . If Li are same then the segment with smaller Ri comes first.
For every line-segment [Li, Ri], the approach below is followed to find the number of odd cases.
- While multiset is not empty, and the lines don’t intersect then delete the line with smallest Ri from multiset and check again.
- Number of violating ways using this segment [Li, Ri] are pCk-1
- where p = size_of_multiset.
- Insert end-point of this line-segment in the multiset.
Below is the implementation of the above approach:
// C++ program to find Number of ways // to choose K intersecting // line segments on X-axis #include <bits/stdc++.h> using namespace std;
const long long mod = 1000000007;
const int MAXN = 1001;
long long factorial[MAXN], inverse[MAXN];
// Function to find (a^b)%mod in log b long long power( long long a, long long b)
{ long long res = 1;
// Till power becomes 0
while (b > 0) {
// If power is odd
if (b % 2 == 1) {
res = (res * a) % mod;
}
// Multiply base
a = (a * a) % mod;
// Divide power by 1
b >>= 1;
}
return res;
} // Function to find nCk long long nCk( int n, int k)
{ // Base case
if (k < 0 || k > n) {
return 0;
}
// Apply formula to find nCk
long long ans = factorial[n];
ans = (ans * inverse[n - k]) % mod;
ans = (ans * inverse[k]) % mod;
return ans;
} // Function to find the number of ways void numberOfWays(vector<pair< int , int > > lines, int K,
int N)
{ // sort the given lines
sort(lines.begin(), lines.end());
// Find the number of total case
long long total_case = nCk(N, K);
// Declare a multiset
multiset< int > m;
// loop till N
for ( int i = 0; i < N; i++)
{
// Check if smallest element is
// smaller than lines[i]
while (!m.empty()
&& (*m.begin() < lines[i].first)) {
// Erase first element
m.erase(m.begin());
}
// Exclude the odd cases
total_case -= nCk(m.size(), K - 1);
// Modulus operation
total_case += mod;
total_case %= mod;
// Insert into multiset
m.insert(lines[i].second);
}
cout << total_case << endl;
} // Function to precompute // factorial and inverse void preCompute()
{ long long fact = 1;
factorial[0] = 1;
inverse[0] = 1;
// Pre-compute factorial and inverse
for ( int i = 1; i < MAXN; i++) {
fact = (fact * i) % mod;
factorial[i] = fact;
inverse[i] = power(factorial[i], mod - 2);
}
} // Driver code int main()
{ int N = 3, K = 2;
vector<pair< int , int > > lines;
// Function to pre-compute
// factorial and inverse
preCompute();
lines.push_back({ 1, 3 });
lines.push_back({ 4, 5 });
lines.push_back({ 5, 7 });
numberOfWays(lines, K, N);
return 0;
} |
// Java program to find Number of ways // to choose K intersecting line // segments on X-axis import java.util.*;
import java.lang.*;
class GFG {
static long mod = 1000000007 ;
static int MAXN = 1001 ;
static long factorial[] = new long [MAXN],
inverse[] = new long [MAXN];
// Function to find (a^b)%mod in log b
static long power( long a, long b)
{
long res = 1 ;
// Till power becomes 0
while (b > 0 ) {
// If power is odd
if (b % 2 == 1 ) {
res = (res * a) % mod;
}
// Multiply base
a = (a * a) % mod;
// Divide power by 1
b >>= 1 ;
}
return res;
}
// Function to find nCk
static long nCk( int n, int k)
{
// Base case
if (k < 0 || k > n) {
return 0 ;
}
// Apply formula to find nCk
long ans = factorial[n];
ans = (ans * inverse[n - k]) % mod;
ans = (ans * inverse[k]) % mod;
return ans;
}
// Function to find the number of ways
static void numberOfWays(ArrayList< int []> lines, int K,
int N)
{
// sort the given lines
Collections.sort(lines, (a, b) -> a[ 0 ] - b[ 0 ]);
// Find the number of total case
long total_case = nCk(N, K);
// Declare a multiset
PriorityQueue<Integer> m = new PriorityQueue<>();
// Loop till N
for ( int i = 0 ; i < N; i++) {
// Check if smallest element is
// smaller than lines[i]
while (!m.isEmpty()
&& (m.peek() < lines.get(i)[ 0 ])) {
// Erase first element
m.poll();
}
// Exclude the odd cases
total_case -= nCk(m.size(), K - 1 );
// Modulus operation
total_case += mod;
total_case %= mod;
// Insert into multiset
m.add(lines.get(i)[ 1 ]);
}
System.out.println(total_case);
}
// Function to precompute
// factorial and inverse
static void preCompute()
{
long fact = 1 ;
factorial[ 0 ] = 1 ;
inverse[ 0 ] = 1 ;
// Pre-compute factorial and inverse
for ( int i = 1 ; i < MAXN; i++) {
fact = (fact * i) % mod;
factorial[i] = fact;
inverse[i] = power(factorial[i], mod - 2 );
}
}
// Driver code
public static void main(String[] args)
{
int N = 3 , K = 2 ;
ArrayList< int []> lines = new ArrayList<>();
// Function to pre-compute
// factorial and inverse
preCompute();
lines.add( new int [] { 1 , 3 });
lines.add( new int [] { 4 , 5 });
lines.add( new int [] { 5 , 7 });
numberOfWays(lines, K, N);
}
} // This code is contributed by offbeat |
# Python3 program to find Number of ways # to choose K ersecting # line segments on X-axis import heapq as hq
mod = 1000000007
MAXN = 1001
factorial = [ 1 ] * MAXN; inverse = [ 1 ] * MAXN
# Function to find (a^b)%mod in log b def power(a, b):
res = 1
# Till power becomes 0
while (b > 0 ) :
# If power is odd
if (b % 2 = = 1 ) :
res = (res * a) % mod
# Multiply base
a = (a * a) % mod
# Divide power by 1
b >> = 1
return res
# Function to find nCk def nCk(n, k):
# Base case
if (k < 0 or k > n) :
return 0
# Apply formula to find nCk
ans = factorial[n]
ans = (ans * inverse[n - k]) % mod
ans = (ans * inverse[k]) % mod
return ans
# Function to find the number of ways def numberOfWays(lines, K, N):
# sort the given lines
lines.sort()
# Find the number of total case
total_case = nCk(N, K)
# Declare a heap
m = []
# loop till N
for i in range (N):
# Check if smallest element is
# smaller than lines[i]
while (m and m[ 0 ] < lines[i][ 0 ]):
# Erase first element
hq.heappop(m)
# Exclude the odd cases
total_case - = nCk( len (m), K - 1 )
# Modulus operation
total_case + = mod
total_case % = mod
# Insert into heap
hq.heappush(m,lines[i][ 1 ])
print (total_case)
# Function to precompute # factorial and inverse def preCompute():
global factorial
fact = 1
factorial[ 0 ] = 1
inverse[ 0 ] = 1
# Pre-compute factorial and inverse
for i in range ( 1 ,MAXN) :
fact = (fact * i) % mod
factorial[i] = fact
inverse[i] = power(factorial[i], mod - 2 )
# Driver code if __name__ = = '__main__' :
N = 3 ; K = 2
lines = []
# Function to pre-compute
# factorial and inverse
preCompute()
lines.append(( 1 , 3 ))
lines.append(( 4 , 5 ))
lines.append(( 5 , 7 ))
numberOfWays(lines, K, N)
|
// C// program to find Number of ways // to choose K ersecting // line segments on X-axis using System;
using System.Collections.Generic;
namespace ConsoleApp1
{ class Program
{
const int mod = 1000000007;
const int MAXN = 1001;
static long [] factorial = new long [MAXN];
static long [] inverse = new long [MAXN];
// Driver code
static void Main( string [] args)
{
int N = 3, K = 2;
List<( int , int )> lines = new List<( int , int )>();
// Function to pre-compute
// factorial and inverse
PreCompute();
lines.Add((1, 3));
lines.Add((4, 5));
lines.Add((5, 7));
NumberOfWays(lines, K, N);
}
// Function to precompute
// factorial and inverse
static void PreCompute()
{
long fact = 1;
factorial[0] = 1;
inverse[0] = 1;
// Pre-compute factorial and inverse
for ( int i = 1; i < MAXN; i++)
{
fact = (fact * i) % mod;
factorial[i] = fact;
inverse[i] = Power(factorial[i], mod - 2);
}
}
// Function to find (a^b)%mod in log b
static long Power( long a, int b)
{
long res = 1;
// Till power becomes 0
while (b > 0)
{
// If power is odd
if (b % 2 == 1)
{
res = (res * a) % mod;
}
// Multiply base
a = (a * a) % mod;
// Divide power by 1
b >>= 1;
}
return res;
}
// Function to find nCk
static long NCk( int n, int k)
{
// Base case
if (k < 0 || k > n)
{
return 0;
}
// Apply formula to find nCk
long ans = factorial[n];
ans = (ans * inverse[n - k]) % mod;
ans = (ans * inverse[k]) % mod;
return ans;
}
// Function to find the number of ways
static void NumberOfWays(List<( int , int )> lines, int K, int N)
{
// sort the given lines
lines.Sort();
// Find the number of total case
long total_case = NCk(N, K);
// Declare a heap
List< int > m = new List< int >();
// loop till N
for ( int i = 0; i < N; i++)
{
// Check if smallest element is
// smaller than lines[i]
while (m.Count > 0 && m[0] < lines[i].Item1)
{
// Erase first element
m.RemoveAt(0);
}
// Exclude the odd cases
total_case -= NCk(m.Count, K - 1);
// Modulus operation
total_case += mod;
total_case %= mod;
// Insert into heap
m.Add(lines[i].Item2);
}
Console.WriteLine(total_case);
}
}
} // this code is contributed by Shivhack999 |
2
Time Complexity: O(MAXN * log(MAXN) + N * log(N)).
Auxiliary Space: O(MAXN + N).