Related Articles

Related Articles

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

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Output

2

competitive-programming-img




My Personal Notes arrow_drop_up
Recommended Articles
Page :