📌  相关文章
📜  使用索引完全除 K 的元素的所有大小为 K 的排序子集的乘积

📅  最后修改于: 2021-09-17 06:47:15             🧑  作者: Mango

给定一个由N 个不同元素组成的整数数组arr[]和一个正整数K ( K <= N )。任务是使用索引完全除 K 的元素,从给定的数组中计算所有大小为 K 的排序子集的乘积。

注意:由于答案可能非常大,请以 10^9+7 为模打印。

例子:

天真的方法:

我们可以找到所有大小为 K 的子集,然后对子集进行排序并找到每个子集的值并将其相乘得到最终答案。
由于可以有 2 N个子集,这种方法对于较大的 N 值不是很有效。

有效的方法:

  • 这个想法不是创建所有子集来找到答案,而是计算所有子集中每个元素的计数。如果我们找到所有子集中每个元素的计数,那么答案将是
  • 为了找到 arr[i] 的计数,我们必须找到可以通过将 arr[i] 放置在可以完全划分 K 的每个可能索引处形成的不同子集的总数。
  • 通过将 arr[i] 放在j索引处(j 完全除掉 K)形成的集合数将为:
  • 由于任何元素的数量可能非常大,因此为了找到 (arr[i] (count of arr[i]) ) % ( 10 9 + 7 ) 我们必须使用费马小定理,即

所以,通过使用费马小定理

下面是上述方法的实现:

C++
// C++ implementation of the above approach
 
#include 
using namespace std;
int p = 1000000007;
 
// Iterative Function to calculate
// (x^y)%p in O(log y)
long long int power(long long int x,
                    long long int y,
                    long long int p)
{
    long long int res = 1;
    x = x % p;
    while (y > 0) {
 
        // If y is odd, multiply
        // x with result
        if (y & 1)
            res = (res * x) % p;
 
        // y must be even now
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
 
// Iterative Function to calculate
// (nCr)%p and save in f[n][r]
void nCr(long long int n, long long int p,
         int f[][100], int m)
{
 
    for (long long int i = 0; i <= n; i++) {
        for (long long int j = 0; j <= m; j++) {
 
            // If j>i then C(i, j) = 0
            if (j > i) {
                f[i][j] = 0;
            }
 
            // If iis equal to j then
            // C(i, j) = 1
            else if (j == 0 || j == i) {
                f[i][j] = 1;
            }
 
            else {
                f[i][j] = (f[i - 1][j]
                           + f[i - 1][j - 1])
                          % p;
            }
        }
    }
}
 
// Function calculate the Final answer
void ProductOfSubsets(int arr[], int n,
                      int m)
{
    int f[n + 1][100];
 
    nCr(n, p - 1, f, m);
 
    sort(arr, arr + n);
 
    // Initialize ans
    long long int ans = 1;
 
    for (long long int i = 0; i < n; i++) {
 
        // x is count of occurence of arr[i]
        // in different set such that index
        // of arr[i] in those sets divides
        // K completely.
        long long int x = 0;
 
        for (long long int j = 1; j <= m; j++) {
 
            // Finding the count of arr[i] by
            // placing it at index which
            // divides K completely
            if (m % j == 0) {
 
                // By Fermat's theorem
                x = (x
                     + (f[n - i - 1][m - j]
                        * f[i][j - 1])
                           % (p - 1))
                    % (p - 1);
            }
        }
 
        ans
            = ((ans * power(arr[i], x, p)) % p);
    }
 
    cout << ans << endl;
}
 
// Driver code
int main()
{
 
    int arr[] = { 4, 5, 7, 9, 3 };
    int K = 4;
 
    int N = sizeof(arr) / sizeof(arr[0]);
 
    ProductOfSubsets(arr, N, K);
 
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
 
class GFG{
static int p = 1000000007;
 
// Iterative Function to calculate
// (x^y)%p in O(log y)
static int power(int x, int y, int p)
{
    int res = 1;
    x = x % p;
    while (y > 0)
    {
         
        // If y is odd, multiply
        // x with result
        if (y % 2 == 1)
            res = (res * x) % p;
 
        // y must be even now
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
 
// Iterative Function to calculate
// (nCr)%p and save in f[n][r]
static void nCr(int n, int p,
                int f[][], int m)
{
    for(int i = 0; i <= n; i++)
    {
       for(int j = 0; j <= m; j++)
       {
            
          // If j>i then C(i, j) = 0
          if (j > i)
          {
              f[i][j] = 0;
          }
           
          // If iis equal to j then
          // C(i, j) = 1
          else if (j == 0 || j == i)
          {
              f[i][j] = 1;
          }
          else
          {
              f[i][j] = (f[i - 1][j] +
                         f[i - 1][j - 1]) % p;
          }
       }
    }
}
 
// Function calculate the Final answer
static void ProductOfSubsets(int arr[], int n,
                                        int m)
{
    int [][]f = new int[n + 1][100];
 
    nCr(n, p - 1, f, m);
    Arrays.sort(arr);
 
    // Initialize ans
    long ans = 1;
 
    for(int i = 0; i < n; i++)
    {
         
       // x is count of occurence of arr[i]
       // in different set such that index
       // of arr[i] in those sets divides
       // K completely.
       int x = 0;
        
       for(int j = 1; j <= m; j++)
       {
            
          // Finding the count of arr[i] by
          // placing it at index which
          // divides K completely
          if (m % j == 0)
          {
               
              // By Fermat's theorem
              x = (x + (f[n - i - 1][m - j] *
                        f[i][j - 1]) %
                        (p - 1)) %
                        (p - 1);
          }
       }
       ans = ((ans * power(arr[i], x, p)) % p);
    }
    System.out.print(ans + "\n");
}
 
// Driver code
public static void main(String[] args)
{
 
    int arr[] = { 4, 5, 7, 9, 3 };
    int K = 4;
    int N = arr.length;
 
    ProductOfSubsets(arr, N, K);
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation of the above approach
p = 1000000007
 
# Iterative Function to calculate
# (x^y)%p in O(log y)
def power(x, y, p):
    res = 1
    x = x % p
     
    while (y > 0):
         
        # If y is odd, multiply
        # x with result
        if (y & 1):
            res = (res * x) % p
             
        # y must be even now
        y = y >> 1
        x = (x * x) % p
         
    return res
 
# Iterative Function to calculate
# (nCr)%p and save in f[n][r]
def nCr(n, p, f, m):
     
    for i in range(n + 1):
        for j in range(m + 1):
             
            # If j>i then C(i, j) = 0
            if (j > i):
                f[i][j] = 0
 
            # If i is equal to j then
            # C(i, j) = 1
            elif(j == 0 or j == i):
                f[i][j] = 1
                 
            else:
                f[i][j] = (f[i - 1][j] +
                           f[i - 1][j - 1]) % p
 
# Function calculate the Final answer
def ProductOfSubsets(arr, n, m):
     
    f = [[0 for i in range(100)]
            for j in range(n + 1)]
 
    nCr(n, p - 1, f, m)
    arr.sort(reverse = False)
 
    # Initialize ans
    ans = 1
     
    for i in range(n):
         
        # x is count of occurence of arr[i]
        # in different set such that index
        # of arr[i] in those sets divides
        # K completely.
        x = 0
 
        for j in range(1, m + 1, 1):
             
            # Finding the count of arr[i] by
            # placing it at index which
            # divides K completely
            if (m % j == 0):
                 
                # By Fermat's theorem
                x = ((x + (f[n - i - 1][m - j] *
                           f[i][j - 1]) %
                               (p - 1)) %
                               (p - 1))
 
        ans = ((ans * power(arr[i], x, p)) % p)
 
    print(ans)
 
# Driver code
if __name__ == '__main__':
     
    arr = [ 4, 5, 7, 9, 3 ]
    K = 4
    N = len(arr);
 
    ProductOfSubsets(arr, N, K)
 
# This code is contributed by samarth


C#
// C# implementation of the above approach
using System;
class GFG{
     
static int p = 1000000007;
 
// Iterative Function to calculate
// (x^y)%p in O(log y)
static int power(int x, int y, int p)
{
    int res = 1;
    x = x % p;
    while (y > 0)
    {
         
        // If y is odd, multiply
        // x with result
        if (y % 2 == 1)
            res = (res * x) % p;
 
        // y must be even now
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
 
// Iterative Function to calculate
// (nCr)%p and save in f[n,r]
static void nCr(int n, int p,
                int [,]f, int m)
{
    for(int i = 0; i <= n; i++)
    {
        for(int j = 0; j <= m; j++)
        {
                 
            // If j>i then C(i, j) = 0
            if (j > i)
            {
                f[i, j] = 0;
            }
                 
            // If iis equal to j then
            // C(i, j) = 1
            else if (j == 0 || j == i)
            {
                f[i, j] = 1;
            }
            else
            {
                f[i, j] = (f[i - 1, j] +
                           f[i - 1, j - 1]) % p;
            }
        }
    }
}
 
// Function calculate the Final answer
static void ProductOfSubsets(int []arr, int n,
                                        int m)
{
    int [,]f = new int[n + 1, 100];
 
    nCr(n, p - 1, f, m);
    Array.Sort(arr);
 
    // Initialize ans
    long ans = 1;
 
    for(int i = 0; i < n; i++)
    {
         
        // x is count of occurence of arr[i]
        // in different set such that index
        // of arr[i] in those sets divides
        // K completely.
        int x = 0;
             
        for(int j = 1; j <= m; j++)
        {
                 
            // Finding the count of arr[i] by
            // placing it at index which
            // divides K completely
            if (m % j == 0)
            {
                     
                // By Fermat's theorem
                x = (x + (f[n - i - 1, m - j] *
                          f[i, j - 1]) %
                              (p - 1)) %
                              (p - 1);
            }
        }
        ans = ((ans * power(arr[i], x, p)) % p);
    }
    Console.Write(ans + "\n");
}
 
// Driver code
public static void Main(String[] args)
{
 
    int []arr = { 4, 5, 7, 9, 3 };
    int K = 4;
    int N = arr.Length;
 
    ProductOfSubsets(arr, N, K);
}
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
808556639

时间复杂度: (N * K)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程