Skip to content
Related Articles

Related Articles

Improve Article

Number of ways to choose K intersecting line segments on X-axis

  • Last Updated : 18 Nov, 2020

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:
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:
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++




// 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




// 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
Output
2

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :