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

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 {n \choose k}.
  • We pre-calculate the inverse and factorial of required numbers to calculate {n \choose k} 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 {p \choose k-1} where p = size_of_multiset.
  • Insert end-point of this line-segment in the multiset.

Below is the implementation of the above approach:

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


Output:

2

competitive-programming-img




My Personal Notes arrow_drop_up

Recommended Posts: