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:
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 ``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 > 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 > 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 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).

Previous
Next