原文:https://www . geeksforgeeks . org/product-of-all-sorted-size-子集-k-use-elements-what-index-divide-k-complete/

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

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

示例:

输入: arr[] = {4,7,5,9,3},k = 4 输出: 808556639 解释: 在这种情况下有 5 个可能的集合: {4,7,5,9} - > 180(排序顺序{4,5,7,9}:索引 1,2,4 除 m,所以集合的值为 4 * 5 * 9 = 180) 3} - > 108 {4,7,5,3} - > 84 {7,5,9,3} - > 135 合计值=(180 * 108 * 108 * 84 * 135)%(109 7)= 808556639

输入: arr[] = {7,8,9},k = 2 输出: 254016

天真方法:

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

有效方法:

  • 其思想不是创建所有子集来寻找答案,而是计算所有子集内每个元素的计数。如果我们找到所有子集中每个元素的计数,那么答案将是
  • 为了找到 arr[i]的计数,我们必须找到不同子集的总数,这些子集可以通过将 arr[i]放置在将 k 完全除的每个可能的索引处而形成。

  • 通过将 arr[i]放置在第 j 索引处(j 完全除 k)形成的集合数将为:

(小于 arr[i]的元素总数) c j-1 * (大于 arr[i]的元素总数)ck-jt10】

  • 由于任何元素的计数都可能很大,所以要求(arr[i](arr[i]))%(109 7)我们就要用到 费马小定理 也就是

{ a(p-1)mod p = 1 } =>{(ax)% p =(a(x % p-1))% p。

所以,利用费马小定理

(arr[i](arr[i]))%(109 7)=>(arr[i](arr[i]% 109 6))%(109 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

python 3

# 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

java 描述语言


output: 

808556639

时间复杂度: (n * k)

辅助空间:o(n * 100)t4】