给定一个由N 个不同元素组成的整数数组arr[]和一个正整数K ( K <= N )。任务是使用索引完全除 K 的元素,从给定的数组中计算所有大小为 K 的排序子集的乘积。
注意:由于答案可能非常大,请以 10^9+7 为模打印。
例子:
Input: arr[] = {4, 7, 5, 9, 3}, K = 4
Output: 808556639
Explanation:
In this case there are 5 possible sets:
{4, 7, 5, 9} -> 180 (Sorted order {4, 5, 7, 9}: Index 1, 2 and 4 divides M, so value of set is 4 * 5 * 9 = 180)
{4, 7, 9, 3} -> 108
{4, 5, 9, 3} -> 108
{4, 7, 5, 3} -> 84
{7, 5, 9, 3} -> 135
Total value = ( 180 * 108 * 108 * 84 * 135 ) % (109+7) = 808556639
Input: arr[] = {7, 8, 9}, K = 2
Output: 254016
天真的方法:
我们可以找到所有大小为 K 的子集,然后对子集进行排序并找到每个子集的值并将其相乘得到最终答案。
由于可以有 2 N个子集,这种方法对于较大的 N 值不是很有效。
有效的方法:
- 这个想法不是创建所有子集来找到答案,而是计算所有子集中每个元素的计数。如果我们找到所有子集中每个元素的计数,那么答案将是
- 为了找到 arr[i] 的计数,我们必须找到可以通过将 arr[i] 放置在可以完全划分 K 的每个可能索引处形成的不同子集的总数。
- 通过将 arr[i] 放在第j个索引处(j 完全除掉 K)形成的集合数将为:
( Total no. of elements smaller than arr[i] ) Cj-1 * ( Total no. of elements greater than arr[i] ) Ck-j
- 由于任何元素的数量可能非常大,因此为了找到 (arr[i] (count of arr[i]) ) % ( 10 9 + 7 ) 我们必须使用费马小定理,即
{ a (p – 1) mod p = 1 } => { ( ax ) % p = ( a( x % p-1 )) % p }.
所以,通过使用费马小定理
( arr[i] (count of arr[i] )) % ( 109 + 7 ) => ( arr[i] (count of 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
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 现场工作专业课程和学生竞争性编程现场课程。