I have to print the number of ways you can represent a given number as it\'s prime number parts.
Let me clarify: Let\'s say I have been given this number 7. Now, fir
The concept you are searching for is the "prime partitions" of a number. S partition of a number is a way of adding numbers to reach the target; for instance, 1+1+2+3 is a partition of 7. If all the addends are prime, then the partition is a prime partition.
I think your example is wrong. The number 7 is usually considered to have 3 prime partitions: 2+2+3, 2+5, and 7. The order of the addends doesn't matter. In number theory the function that counts prime partitions is kappa, so we would say kappa(7) = 3.
The usual calculation of kappa is done in two parts. The first part is a function to compute the sum of the prime factors of a number; for instance, 42=2·3·7, so sopf(42)=12. Note that sopf(12)=5 because the sum is over only the distinct factors of a number, so even though 12=2·2·3, only one 2 is included in the calculation of the sum.
Given sopf, there is a lengthy formula to calculate kappa; I'll give it in LaTeX form, since I don't know how to enter it here: \kappa(n) = \frac{1}{n}\left(\mathrm{sopf}(n) + \sum_{j=1}^{n-1} \mathrm{sopf}(j) \cdot \kappa(n-j)\right).
If you actually want a list of the partitions, instead of just the count, there is a dynamic programming solution that @corsiKa pointed out.
I discuss prime partitions in more detail at my blog, including source code to produce both the count and the list.
Here's an efficient implementation which uses dynamic programming like corsiKa suggests, but does not use the algorithm he describes.
Simply: if n
is reachable via k
distinct paths (including the single-step one, if it exists), and p
is prime, then we construct k
paths to n+p
by appending p
to all paths to n
. Considering all such n < N
will produce an exhaustive list of valid paths to N
. So we just sum the number of paths so discovered.
#include <iostream>
int primes_all[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
const int N_max = 85;
typedef long long ways;
ways ways_to_reach_N[N_max + 1] = { 1 };
int main()
{
// find all paths
for( int i = 0; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
for( int* p = primes_all; *p <= N_max - i && p < (&primes_all)[1]; ++p ) {
ways_to_reach_N[i + *p] += ways_to_reach_i;
}
}
}
// eliminate single-step paths
for( int* p = primes_all; *p <= N_max && p < (&primes_all)[1]; ++p ) {
--ways_to_reach_N[*p];
}
// print results
for( int i = 1; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
std::cout << i << " -- " << ways_to_reach_i << std::endl;
}
}
return 0;
}
Replacing the typedef ways
with a big integer type is left as an exercise to the reader.
Dynamic programming is your friend here.
Consider the number 27.
If 7 has 5 results, and 20 has 732 results, then you know that 27 has at least (732 * 5) results. You can use a two variable system (1 + 26, 2 + 25 ... etc) using the precomputed values for those as you go. You don't have to recompute 25 or 26 because you already did them.