📜  从两个不同的集合中选择一对或多对的方法

📅  最后修改于: 2021-05-04 08:35:14             🧑  作者: Mango

给定两个正数“ n”和“ m”(n <= m),分别代表第一和第二类集合的项总数。通过选择第一种(I)中的一项和第二种(II)中的另一项,找到选择至少一对的方法的总数。在任何布置中,一个项目都不应该在任何两对之间是相同的。
注意:由于答案可能很大,因此请以1000000007为模输出。

Input: 2 2
Output: 6
Explanation
Let's denote the items of I type
as a, b and II type as c, d i.e,
Type I -  a, b
Type II - c, d
Ways to arrange one pair at a time
1. a --- c
2. a --- d
3. b --- c
4. b --- d
Ways to arrange two pairs at a time
5. a --- c, b --- d
6. a --- d, b --- c

Input: 2 3
Output: 12

Input: 1 2
Output: 2

方法很简单,我们只需要选择的“”的项目从“N”型和其中的“i”1变化相结合,从“M”“I”项目,并乘其(产品的规则),以“N” 。但是我们也可以用“ i”方式置换生成的乘积,因此我们需要与i相乘 。之后,取所有结果乘积的和(Rule of sum)以获得最终答案。

\implies\displaystyle \sum_{i=1}^{\text{n}} {}^n\text C_i\cdot{}^m\text C_i \cdot i!\implies\displaystyle \sum_{i=1}^{\text{n}} \frac{n!}{i!(n-i)!}\cdot \frac{m!}{i!(m-i)!}\cdot i!\implies\displaystyle \sum_{i=1}^{\text{n}} \frac{n!}{(n-i)!}\cdot \frac{m!}{(m-i)!}\cdot \frac{1}{i!}\implies\displaystyle\sum_{i=1}^{\text{n}} \frac{{}^n\text P_i\cdot{}^m\text P_i}{i}

C++
// C++ program to find total no. of ways
// to form a pair in two different set
#include 
using namespace std;
  
// initialize global variable so that
// it can access by preCalculate() and
// nCr() function
int* fact, *inverseMod;
const int mod = 1e9 + 7;
  
/* Iterative Function to calculate (x^y)%p in O(log y) */
int power(int x, int y, int p)
{
    int res = 1; // Initialize result
  
    x = x % p; // Update x if it is more than or
               // equal to p
  
    while (y) {
  
        // If y is odd, multiply x with result
        if (y & 1)
            res = (1LL * res * x) % p;
  
        // y must be even now
        y = y >> 1; // y = y/2
        x = (1LL * x * x) % p;
    } // trace(res);
  
    return res;
}
  
// Pre-calculate factorial and
// Inverse of number
void preCalculate(int n)
{
    fact[0] = inverseMod[0] = 1;
    for (int i = 1; i <= n; ++i) {
  
        fact[i] = (1LL * fact[i - 1] * i) % mod;
        inverseMod[i] = power(fact[i], mod - 2, mod);
    }
}
  
// utility function to calculate nCr
int nPr(int a, int b)
{
    return (1LL * fact[a] * inverseMod[a - b]) % mod;
}
  
int countWays(int n, int m)
{
    fact = new int[m + 1];
    inverseMod = new int[m + 1];
  
    // Pre-calculate factorial and
    // inverse of number
    preCalculate(m);
  
    // Initialize answer
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
  
        ans += (1LL * ((1LL * nPr(n, i) 
                * nPr(m, i)) % mod)
                * inverseMod[i]) % mod;
        if (ans >= mod)
            ans %= mod;
    }
  
    return ans;
}
  
// Driver program
int main()
{
    int n = 2, m = 2;
  
    cout << countWays(n, m);
  
    return 0;
}


Java
// Java program to find total
// no. of ways to form a pair
// in two different set
  
public class Test
{
    static long[] fact;
    static long[] inverseMod;
    static int mod=1000000007;
      
    /* Iterative Function to calculate 
       (x^y)%p in O(log y) */
      
    static long power(long x, int y, int p)
    {
        // Initialize result
        long res = 1; 
      
        // Update x if it is more than or
        // equal to p
        x = x % p; 
      
        while (y!=0)
        {
      
            // If y is odd, multiply 
            // x with result
            if ((y & 1)!=0)
                res = (1 * res * x) % p;
            }
            // y must be even now
            y = y >> 1; 
              
            x = (1 * x * x) % p;
        } 
      
      
        return res;
    }
      
    // Pre-calculate factorial and
    // Inverse of number
    public static void preCalculate(int n)
    {
        //int fact[]=new long[n];
        // int inverseMod[]=new long[n];
        fact[0] = 1;
        inverseMod[0] = 1;
          
        for (int i = 1; i <= n; i++) 
        {
          
                fact[i] = (1 * fact[i - 1] * i)
                                          % mod;
                                            
                inverseMod[i] = power(fact[i], 
                                  mod - 2, mod);
              
        }
    }
      
    // utility function to calculate nCr
    public static long nPr(int a, int b)
    {
          
        return (1 * fact[a] * inverseMod[a - b])
                                    % (long)mod;
    }
          
    public static int countWays(int n, int m)
    {
          
        fact = new long[m + 1];
        inverseMod = new long[m + 1];
          
        // Pre-calculate factorial and
        // inverse of number
        preCalculate(m);
      
        // Initialize answer
        long ans = 0;
          
        for (int i = 1; i <= n; i++) {
      
            ans = ans+(1 * ((1 * nPr(n, i)* 
                                nPr(m, i)) % mod)*
                                (inverseMod[i])) % mod;
                                            
            if (ans >= mod)
                ans %= mod;
        }
      
        return (int)ans;
     } 
      
    /* Driver program */
    public static void main(String[] args) 
    {
        int n = 2, m = 2;
          
        System.out.println(countWays(n, m));
    }
}
  
// This code is contributed by Gitanjali


输出:

6

时间复杂度: O(m * log(mod))
辅助空间: O(m)