给定一个整数N和一个整数K ,任务是计算将N表示为K个唯一素数之和的不同方式的数量。
注意:不同的意思是,让N = 7并且K = 2,则唯一的方法可以是{2,5},因为{5,2}与{2,5}相同。所以只有一种方法。
例子:
Input: N = 10, K = 2
Output: 1
Explanation:
The only way is {3, 7} or {7, 3}
Input: N = 100, K = 5
Output: 55
方法:可以使用动态编程和Eratosthenes筛子解决问题。
- 令dp [i] [j] [sum]为我们的3D DP数组,该数组存储使用j个素数(其中素数的最后一个索引为i的i)形成求和的不同方式的数目。
- 质数可以使用Eratosthenes的Sieve进行有效地计算。因此,我们可以检查O(1)时间中的质数。
- 复发:
We can either include this current prime to our sum, or we can exclude it.
dp[i][j][sum] = solve(i+1, j+1, sum+prime[i]) + solve(i+1, j, sum)
下面是上述方法的实现:
C++
// C++ program to count the Number
// of distinct ways to represent
// a number as K different primes
#include
using namespace std;
// Prime vector
vector prime;
// Sieve array of prime
bool isprime[1000];
// DP array
int dp[200][20][1000];
void sieve()
{
// Initialise all numbers
// as prime
memset(isprime, true,
sizeof(isprime));
// Sieve of Eratosthenes.
for (int i = 2; i * i <= 1000;
i++)
{
if (isprime[i])
{
for (int j = i * i;
j <= 1000; j += i)
{
isprime[j] = false;
}
}
}
// Push all the primes into
// prime vector
for (int i = 2; i <= 1000; i++)
{
if (isprime[i])
{
prime.push_back(i);
}
}
}
// Function to get the number of
// distinct ways to get sum
// as K different primes
int CountWays(int i, int j, int sum,
int n, int k)
{
// If index went out of prime
// array size or the sum became
// larger than n return 0
if (i > prime.size() || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n) {
if (j == k) {
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i][j][sum])
return dp[i][j][sum];
int inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime[i],
n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum,
n, k);
// Return by memoizing the ans
return dp[i][j][sum] = inc + exc;
}
// Driver code
int main()
{
// Precompute primes by sieve
sieve();
int N = 100, K = 5;
cout << CountWays(0, 0, 0, N, K);
}
Java
// Java program to count the number
// of distinct ways to represent
// a number as K different primes
import java.io.*;
import java.util.*;
class GFG{
// Prime vector
static ArrayList prime = new ArrayList();
// Sieve array of prime
static boolean[] isprime = new boolean[1000];
// DP array
static int[][][] dp = new int[200][20][1000];
static void sieve()
{
// Initialise all numbers
// as prime
for(int i = 0; i < 1000; i++)
isprime[i] = true;
// Sieve of Eratosthenes.
for(int i = 2; i * i < 1000; i++)
{
if (isprime[i])
{
for(int j = i * i;
j < 1000; j += i)
{
isprime[j] = false;
}
}
}
// Push all the primes into
// prime vector
for(int i = 2; i < 1000; i++)
{
if (isprime[i])
{
prime.add(i);
}
}
}
// Function to get the number of
// distinct ways to get sum
// as K different primes
static int CountWays(int i, int j, int sum,
int n, int k)
{
// If index went out of prime
// array size or the sum became
// larger than n return 0
if (i >= prime.size() - 1 || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n)
{
if (j == k)
{
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i][j][sum] != 0)
return dp[i][j][sum];
int inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime.get(i),
n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum, n, k);
// Return by memoizing the ans
return dp[i][j][sum] = inc + exc;
}
// Driver code
public static void main(String[] args)
{
// Precompute primes by sieve
sieve();
int N = 100, K = 5;
System.out.println(CountWays(0, 0, 0, N, K));
}
}
// This code is contributed by akhilsaini
Python3
# Python3 program to count the number
# of distinct ways to represent
# a number as K different primes
# Prime list
prime = []
# Sieve array of prime
isprime = [True] * 1000
# DP array
dp = [[['0' for col in range(200)]
for col in range(20)]
for row in range(1000)]
def sieve():
# Sieve of Eratosthenes.
for i in range(2, 1000):
if (isprime[i]):
for j in range(i * i, 1000, i):
isprime[j] = False
# Push all the primes into
# prime vector
for i in range(2, 1000):
if (isprime[i]):
prime.append(i)
# Function to get the number of
# distinct ways to get sum
# as K different primes
def CountWays(i, j, sums, n, k):
# If index went out of prime
# array size or the sum became
# larger than n return 0
if (i >= len(prime) or sums > n):
return 0
# If sum becomes equal to n and
# j becomes exactly equal to k.
# Return 1, else if j is still
# not equal to k, return 0
if (sums == n):
if (j == k):
return 1
return 0
# If sum!=n and still j as
# exceeded, return 0
if j == k:
return 0
# If that state is already
# calculated, return directly
# the ans
if dp[i][j][sums] == 0:
return dp[i][j][sums]
inc = 0
exc = 0
# Include the current prime
inc = CountWays(i + 1, j + 1,
sums + prime[i],
n, k)
# Exclude the current prime
exc = CountWays(i + 1, j, sums, n, k)
# Return by memoizing the ans
dp[i][j][sums] = inc + exc
return dp[i][j][sums]
# Driver code
if __name__ == "__main__":
# Precompute primes by sieve
sieve()
N = 100
K = 5
print(CountWays(0, 0, 0, N, K))
# This code is contributed by akhilsaini
C#
// C# program to count the number
// of distinct ways to represent
// a number as K different primes
using System;
using System.Collections.Generic;
class GFG{
// Prime vector
static List prime = new List();
// Sieve array of prime
static bool[] isprime = new bool[1000];
// DP array
static int[, , ] dp = new int[200, 20, 1000];
static void sieve()
{
// Initialise all numbers
// as prime
for(int i = 0; i < 1000; i++)
isprime[i] = true;
// Sieve of Eratosthenes.
for(int i = 2; i * i < 1000; i++)
{
if (isprime[i])
{
for(int j = i * i;
j < 1000; j += i)
{
isprime[j] = false;
}
}
}
// Push all the primes into
// prime vector
for(int i = 2; i < 1000; i++)
{
if (isprime[i])
{
prime.Add(i);
}
}
}
// Function to get the number of
// distinct ways to get sum
// as K different primes
static int CountWays(int i, int j, int sum,
int n, int k)
{
// If index went out of prime
// array size or the sum became
// larger than n return 0
if (i >= prime.Count - 1 || sum > n)
{
return 0;
}
// If sum becomes equal to n and
// j becomes exactly equal to k.
// Return 1, else if j is still
// not equal to k, return 0
if (sum == n)
{
if (j == k)
{
return 1;
}
return 0;
}
// If sum!=n and still j as
// exceeded, return 0
if (j == k)
return 0;
// If that state is already
// calculated, return directly
// the ans
if (dp[i, j, sum] != 0)
return dp[i, j, sum];
int inc = 0, exc = 0;
// Include the current prime
inc = CountWays(i + 1, j + 1,
sum + prime[i], n, k);
// Exclude the current prime
exc = CountWays(i + 1, j, sum, n, k);
// Return by memoizing the ans
return dp[i, j, sum] = inc + exc;
}
// Driver code
static public void Main()
{
// Precompute primes by sieve
sieve();
int N = 100, K = 5;
Console.WriteLine(CountWays(0, 0, 0, N, K));
}
}
// This code is contributed by akhilsaini
输出:
55