给定x轴上的线段的数组arr []和整数K ,任务是计算选择K个线段以使其在任何点相交的方式的数量。由于答案可能很大,因此将其打印为模数10 ^ 9 + 7。
例子:
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.
方法:
为了解决上述问题,我们将尝试找出奇数个案例的数量,即那些交集为非空的案例。因此,很明显,我们的答案将是“全案–奇案”。
要计算案件总数,请采用以下方法:
- 可能的总情况为“ n选择k”或n C k
- 我们预先计算所需数字的逆和阶乘以计算n C k
- 在O(1)时间
- 在考虑线段[Li,Ri]的情况下,K个线段相交,好像min(R1,R2,..,R {k-1})> = Li。保持多集,保持秩序。首先,按Li的升序对段进行排序。如果Li相同,则Ri较小的段首先出现。
对于每个行段[Li,Ri],遵循以下方法来找到奇数个案例。
- 当多重集不为空且线不相交时,请从多重集中删除具有最小Ri的线,然后再次检查。
- 使用该线段[Li,Ri]的违规方式的数量为p C k-1
- 其中p = size_of_multiset。
- 将此线段的端点插入多组中。
下面是上述方法的实现:
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 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 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 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
2