Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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


Python3




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




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


Output

2

Time Complexity: O(MAXN * log(MAXN) + N * log(N)).
Auxiliary Space: O(MAXN + N).



Last Updated : 16 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads