I'm looking to construct an algorithm which gives the arrangements with repetition of n sequences of a given step S (which can be a positive real number), under the constraint that the sum of all combinations is k, with k a positive integer.
My problem is thus to find the solutions to the equation:
x 1 + x 2 + ⋯ + x n = k
where
0 ≤ x i ≤ b i
and S (the step) a real number with finite decimal.
For instance, if 0≤xi≤50, and S=2.5 then xi = {0, 2.5 , 5,..., 47.5, 50}.
The point here is to look only through the combinations having a sum=k because if n is big it is not possible to generate all the arrangements, so I would like to bypass this to generate only the combinations that match the constraint.
I was thinking to start with n=2 for instance, and find all linear combinations that match the constraint.
ex: if xi = {0, 2.5 , 5,..., 47.5, 50} and k=100, then we only have one combination={50,50}
For n=3, we have the combination for n=2 times 3, i.e. {50,50,0},{50,0,50} and {0,50,50} plus the combinations {50,47.5,2.5} * 3! etc...
If xi = {0, 2.5 , 5,..., 37.5, 40} and k=100, then we have 0 combinations for n=2 because 2*40<100, and we have {40,40,20} times 3 for n=3... (if I'm not mistaken)
I'm a bit lost as I can't seem to find a proper way to start the algorithm, knowing that I should have the step S and b as inputs.
Do you have any suggestions?
Thanks
You can transform your problem into an integer problem by dividing everything by S: We want to find all integer sequences y1, ..., yn with:
(1) 0 ≤ yi ≤ ⌊b / S⌋
(2) y1 + ... + yn = k / S
We can see that there is no solution if k is not a multiple of S. Once we have reduced the problem, I would suggest using a pseudopolynomial dynamic programming algorithm to solve the subset sum problem and then reconstruct the solution from it. Let f(i, j) be the number of ways to make sum j with i elements. We have the following recurrence:
f(0,0) = 1
f(0,j) = 0 forall j > 0
f(i,j) = sum_{m = 0}^{min(floor(b / S), j)} f(i - 1, j - m)
We can solve f in O(n * k / S) time by filling it row by row. Now we want to reconstruct the solution. I'm using Python-style pseudocode to illustrate the concept:
def reconstruct(i, j):
if f(i,j) == 0:
return
if i == 0:
yield []
return
for m := 0 to min(floor(b / S), j):
for rest in reconstruct(i - 1, j - m):
yield [m] + rest
result = reconstruct(n, k / S)
result will be a list of all possible combinations.
What you are describing sounds like a special case of the subset sum problem. Once you put it in those terms, you'll find that Pisinger apparently has a linear time algorithm for solving a more general version of your problem, since your weights are bounded. If you're interested in designing your own algorithm, you might start by reading Pisinger's thesis to get some ideas.
Since you are looking for all possible solutions and not just a single solution, the dynamic programming approach is probably your best bet.
Related
Given natural number N (1 <= N <= 2000), count the number of sets of natural numbers with the sum equal to N, if we know that ratio of any two elements in given set is more than 2
(for any x, y in given set: max(x, y) / min(x, y) >= 2)
I am trying to use given ratio so it would be possible to count the sum using geometry progression formula, but I haven't succeeded yet. Somehow it's necessary to come up with dynamic programming solution, but I have no idea how to come up with a formula
As Stef suggested in the comments, if you count the number of ways you can make n, using numbers that are at most k, you can calculate this using dynamic programming. For a given n, k, either you use k or you don't: if you do, then you have n-k left, and can use numbers <= k/2, and if you don't, then you still have n, and can use numbers <= k-1. It's very similar to a coin change algorithm, or to a standard algorithm for counting partitions.
With that, here's a program that prints out the values up to n=2000 in the sequence:
N = 2000
A = [[0] * (i+1) for i in range(N+1)]
A[0][0] = 1
for n in range(1, N+1):
for k in range((n+1)//2, n+1):
A[n][k] = A[n-k][min(n-k, k//2)] + A[n][k-1]
for i in range(N+1):
print(i, A[i][i])
It has a couple of optimizations: A[n, k] is the same as A[n, n] for k>n, and A[n, k]=0 when 2k+1 < N (because if you use k, then the largest integer you can get is at most k+k/2+k/4+... <= 2k-1 -- the infinite sum is 2k, but with integer arithmetic you can never achieve this). These two optimizations give a speedup factor of 2 each, compared to computing the whole (n+1)x(n+1) table.
With these two optimizations, and the array-based bottom-up dynamic programming approach, this prints out all the solutions in around 0.5s on my machine.
Could you please suggest any algorithm ideas for solving the following problem:
Given positive integers S, K ≤ N. Find distinct positive integers x1, x2, ..., xK such that
x12 + x22 + ... + xK2 = S
xi ≤ N and xi < xi+1 for all i = 1...K.
So far I know that I should start searching for the largest x below the square root of S.
Here's a slightly optimised brute force. As I linked to in the comments (and close vote), it seems to me we could modify the standard subset sum problem to work with squares.
JavaScript code (ellipsis at the end of an output means add the rest of the numbers down to 1):
function f(S, K, N){
function g(s, k, n, c){
const minS = k*(k+1)*(2*k+1)/6;
const maxN = Math.min(
n,
~~Math.sqrt(s - (k-1)*k*(2*k-1)/6)
);
if (s < minS || maxN < 1)
return [];
else if (s == minS)
return [c.concat([k, '...'])];
if (k == 0)
return [];
return g(s - maxN*maxN, k - 1, maxN - 1, c.slice().concat(maxN))
.concat(
g(s, k, maxN - 1, c)
);
}
return g(S, K, N, []);
}
for (let j=1; j<6; j++)
console.log(JSON.stringify([178, j, f(178, j, 100)]));
console.log(JSON.stringify([178, 5, f(178, 5, 10)]));
Since you ask for an algorithm idea, and not a precise answer, so here is my 2 cents.
You can transform your problem to get rid of the squares by finding all perfect squares ( e.g. 1, 4, 9, 16, 25...) from 1 to S and put them into a set called PerfectSquareSetLessThanS.
Then, if you can solve the following (more general) problem, you can easily solve your original problem.
General problem:
Given an arbitary set V, find a subset W of V that has exactly K numbers such that they sum to S.
While I don't yet have a precise solution, your general problem looks a lot like a well known problem called the 3SUM problem.
The 3SUM problem asks if given a set of n numbers, are there a set of 3 numbers whose sum is 0. The wikipedia page outlines an algorithm to search for such tupple.
Note that the 3SUM problems have different variants, 1 of which is the k-SUM (substitute 3 by k in the above paragraph) , and another one is the non-zero sum variant. Maybe you could find a combination of these two variants to build your generalized solution.
Suppose n =3
Using the numbers 1 and 2, the combinations to get the sum n would be [1,2], [2,1], [1,1,1]. 3 combinations.
If n= 2
then the combinations to get the sum n would be [1,1] and [2]. 2 combinations.
How do I write an algorithm to compute the number of combinations of 1 and 2 to get the sum to n?
What you are describing seems to be the Coin-Change Problem in the dynamic-programming category. You can check out these links below to gain a better understanding of them -
Coin Change Problem - GeeksForGeeks
Coin Change Problem - Algorithmist
Since just providing a link is not acceptable, i am posting some of the link's content here to give you an idea -
Given a value N, if we want to make change for N cents, and we have infinite supply of each of
S = { S1, S2, .. , Sm} valued coins,
how many ways can we make the change?
The order of coins doesn’t matter.
For example, for N = 4 and S = {1,2,3},
there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}.
So output should be 4.
For N = 10 and S = {2, 5, 3, 6},
there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}.
So the output should be 5.
Optimal Substructure
To count total number solutions, we can divide all set solutions in two sets.
1) Solutions that do not contain mth coin (or Sm).
2) Solutions that contain at least one Sm.
Let count(S[], m, n) be the function to count the number of solutions,
then it can be written as sum of count(S[], m-1, n) and count(S[], m, n-Sm).
Therefore, the problem has optimal substructure property as the problem can be solved using solutions to subproblems.
Overlapping Subproblems
Following is a simple recursive implementation of the Coin Change problem. The implementation simply follows the recursive structure mentioned above.
// Returns the count of ways we can sum S[0...m-1] coins to get sum n
int count( int S[], int m, int n )
{
// If n is 0 then there is 1 solution (do not include any coin)
if (n == 0)
return 1;
// If n is less than 0 then no solution exists
if (n < 0)
return 0;
// If there are no coins and n is greater than 0, then no solution exist
if (m <=0 && n >= 1)
return 0;
// count is sum of solutions (i) including S[m-1] (ii) excluding S[m-1]
return count( S, m - 1, n ) + count( S, m, n-S[m-1] );
}
If you think and dry run the above code you should be able to grasp the basic idea. I hope this solves your problem.
The above explanation :
Courtesy - GeeksforGeeks
This problem can be solved in Mathematics way. The equation is summation of (n-r)Cr where r = 0,1,2,...,n/2 for all n>0
Note that this equation can be further generalize for n>0 and set {1,x} only. Other than this, you should look at the idea provided by #RahulNori
n=4
[1,1,1,1] - 1 combination (4C0)
[2,1,1], [1,2,1], [1,1,2] - 3 combination (3C1)
[2,2] - 1 combination (2C2)
n=5
[1,1,1,1,1] - 1 combination (5C0)
[2,1,1,1], [1,2,1,1], [1,1,2,1], [1,1,1,2] - 4 combination (4C1)
[2,2,1], [2,1,2], [1,2,2] - 3 combination (3C2)
n=6
[1,1,1,1,1,1] - 1 combination (6C0)
[2,1,1,1,1], [1,2,1,1,1], [1,1,2,1,1], [1,1,1,2,1], [1,1,1,1,2] - 5 combination (5C1)
[2,2,1,1], [2,1,2,1], [1,2,2,1], [2,1,1,2], [1,2,1,2], [1,1,2,2] - 6 combination (4C2)
[2,2,2] - 1 combination (3C3)
The question is Number of solutions to a1 x1+a2 x2+....+an xn=k with constraints: 1)ai>0 and ai<=15 2)n>0 and n<=15 3)xi>=0 I was able to formulate a Dynamic programming solution but it is running too long for n>10^10. Please guide me to get a more efficient soution.
The code
int dp[]=new int[16];
dp[0]=1;
BigInteger seen=new BigInteger("0");
while(true)
{
for(int i=0;i<arr[0];i++)
{
if(dp[0]==0)
break;
dp[arr[i+1]]=(dp[arr[i+1]]+dp[0])%1000000007;
}
for(int i=1;i<15;i++)
dp[i-1]=dp[i];
seen=seen.add(new BigInteger("1"));
if(seen.compareTo(n)==0)
break;
}
System.out.println(dp[0]);
arr is the array containing coefficients and answer should be mod 1000000007 as the number of ways donot fit into an int.
Update for real problem:
The actual problem is much simpler. However, it's hard to be helpful without spoiling it entirely.
Stripping it down to the bare essentials, the problem is
Given k distinct positive integers L1, ... , Lk and a nonnegative integer n, how many different finite sequences (a1, ..., ar) are there such that 1. for all i (1 <= i <= r), ai is one of the Lj, and 2. a1 + ... + ar = n. (In other words, the number of compositions of n using only the given Lj.)
For convenience, you are also told that all the Lj are <= 15 (and hence k <= 15), and n <= 10^18. And, so that the entire computation can be carried out using 64-bit integers (the number of sequences grows exponentially with n, you wouldn't have enough memory to store the exact number for large n), you should only calculate the remainder of the sequence count modulo 1000000007.
To solve such a problem, start by looking at the simplest cases first. The very simplest cases are when only one L is given, then evidently there is one admissible sequence if n is a multiple of L and no admissible sequence if n mod L != 0. That doesn't help yet. So consider the next simplest cases, two L values given. Suppose those are 1 and 2.
0 has one composition, the empty sequence: N(0) = 1
1 has one composition, (1): N(1) = 1
2 has two compositions, (1,1); (2): N(2) = 2
3 has three compositions, (1,1,1);(1,2);(2,1): N(3) = 3
4 has five compositions, (1,1,1,1);(1,1,2);(1,2,1);(2,1,1);(2,2): N(4) = 5
5 has eight compositions, (1,1,1,1,1);(1,1,1,2);(1,1,2,1);(1,2,1,1);(2,1,1,1);(1,2,2);(2,1,2);(2,2,1): N(5) = 8
You may see it now, or need a few more terms, but you'll notice that you get the Fibonacci sequence (shifted by one), N(n) = F(n+1), thus the sequence N(n) satisfies the recurrence relation
N(n) = N(n-1) + N(n-2) (for n >= 2; we have not yet proved that, so far it's a hypothesis based on pattern-spotting). Now, can we see that without calculating many values? Of course, there are two types of admissible sequences, those ending with 1 and those ending with 2. Since that partitioning of the admissible sequences restricts only the last element, the number of ad. seq. summing to n and ending with 1 is N(n-1) and the number of ad. seq. summing to n and ending with 2 is N(n-2).
That reasoning immediately generalises, given L1 < L2 < ... < Lk, for all n >= Lk, we have
N(n) = N(n-L1) + N(n-L2) + ... + N(n-Lk)
with the obvious interpretation if we're only interested in N(n) % m.
Umm, that linear recurrence still leaves calculating N(n) as an O(n) task?
Yes, but researching a few of the mentioned keywords quickly leads to an algorithm needing only O(log n) steps ;)
Algorithm for misinterpreted problem, no longer relevant, but may still be interesting:
The question looks a little SPOJish, so I won't give a complete algorithm (at least, not before I've googled around a bit to check if it's a contest question). I hope no restriction has been omitted in the description, such as that permutations of such representations should only contribute one to the count, that would considerably complicate the matter. So I count 1*3 + 2*4 = 11 and 2*4 + 1*3 = 11 as two different solutions.
Some notations first. For m-tuples of numbers, let < | > denote the canonical bilinear pairing, i.e.
<a|x> = a_1*x_1 + ... + a_m*x_m. For a positive integer B, let A_B = {1, 2, ..., B} be the set of positive integers not exceeding B. Let N denote the set of natural numbers, i.e. of nonnegative integers.
For 0 <= m, k and B > 0, let C(B,m,k) = card { (a,x) \in A_B^m × N^m : <a|x> = k }.
Your problem is then to find \sum_{m = 1}^15 C(15,m,k) (modulo 1000000007).
For completeness, let us mention that C(B,0,k) = if k == 0 then 1 else 0, which can be helpful in theoretical considerations. For the case of a positive number of summands, we easily find the recursion formula
C(B,m+1,k) = \sum_{j = 0}^k C(B,1,j) * C(B,m,k-j)
By induction, C(B,m,_) is the convolution¹ of m factors C(B,1,_). Calculating the convolution of two known functions up to k is O(k^2), so if C(B,1,_) is known, that gives an O(n*k^2) algorithm to compute C(B,m,k), 1 <= m <= n. Okay for small k, but our galaxy won't live to see you calculating C(15,15,10^18) that way. So, can we do better? Well, if you're familiar with the Laplace-transformation, you'll know that an analogous transformation will convert the convolution product to a pointwise product, which is much easier to calculate. However, although the transformation is in this case easy to compute, the inverse is not. Any other idea? Why, yes, let's take a closer look at C(B,1,_).
C(B,1,k) = card { a \in A_B : (k/a) is an integer }
In other words, C(B,1,k) is the number of divisors of k not exceeding B. Let us denote that by d_B(k). It is immediately clear that 1 <= d_B(k) <= B. For B = 2, evidently d_2(k) = 1 if k is odd, 2 if k is even. d_3(k) = 3 if and only if k is divisible by 2 and by 3, hence iff k is a multiple of 6, d_3(k) = 2 if and only if one of 2, 3 divides k but not the other, that is, iff k % 6 \in {2,3,4} and finally, d_3(k) = 1 iff neither 2 nor 3 divides k, i.e. iff gcd(k,6) = 1, iff k % 6 \in {1,5}. So we've seen that d_2 is periodic with period 2, d_3 is periodic with period 6. Generally, like reasoning shows that d_B is periodic for all B, and the minimal positive period divides B!.
Given any positive period P of C(B,1,_) = d_B, we can split the sum in the convolution (k = q*P+r, 0 <= r < P):
C(B,m+1, q*P+r) = \sum_{c = 0}^{q-1} (\sum_{j = 0}^{P-1} d_B(j)*C(B,m,(q-c)*P + (r-j)))
+ \sum_{j = 0}^r d_B(j)*C(B,m,r-j)
The functions C(B,m,_) are no longer periodic for m >= 2, but there are simple formulae to obtain C(B,m,q*P+r) from C(B,m,r). Thus, with C(B,1,_) = d_B and C(B,m,_) known up to P, calculating C(B,m+1,_) up to P is an O(P^2) task², getting the data necessary for calculating C(B,m+1,k) for arbitrarily large k, needs m such convolutions, hence that's O(m*P^2).
Then finding C(B,m,k) for 1 <= m <= n and arbitrarily large k is O(n^2*P^2), in time and O(n^2*P) in space.
For B = 15, we have 15! = 1.307674368 * 10^12, so using that for P isn't feasible. Fortunately, the smallest positive period of d_15 is much smaller, so you get something workable. From a rough estimate, I would still expect the calculation of C(15,15,k) to take time more appropriately measured in hours than seconds, but it's an improvement over O(k) which would take years (for k in the region of 10^18).
¹ The convolution used here is (f \ast g)(k) = \sum_{j = 0}^k f(j)*g(k-j).
² Assuming all arithmetic operations are O(1); if, as in the OP, only the residue modulo some M > 0 is desired, that holds if all intermediate calculations are done modulo M.
I was wondering how to solve such a problem using DP.
Given n balls and m bins, each bin having max. capacity c1, c2,...cm. What is the total number of ways of distributing these n balls into these m bins.
The problem I face is
How to find a recurrence relation (I could when the capacities were all a single constant c).
There will be several test cases, each having its own set of c1,c2....cm. So how would the DP actually apply for all these test cases because the answer explicitly depends on present c1,c2....cm, and I can't store (or pre-compute) the answer for all combinations of c1,c2....cm.
Also, I could not come up with any direct combinatoric formula for this problem too, and I don't think one exists too.
You can define your function assuming the limits c[0], c[1], ... c[m-1] as fixed and then writing the recursive formula that returns the number of ways you can distribute n balls into bins starting at index k. With this approach a basic formula is simply
def solutions(n, k):
if n == 0:
return 1 # Out of balls, there's only one solution (0, 0, 0, 0 ... 0)
if k == m:
return 0 # Out of bins... no solutions
total = 0
for h in xrange(0, min(n, c[k])+1): # from 0 to c[k] (included) into bin k
total += solutions(n - h, k + 1)
return total
then you need to add memoization (this will be equivalent to a DP approach) and some other optimizations like e.g. that if n > c[k] + c[k+1] + c[k+2] + ... then you know there are no solutions without the need to search (and you can precompute the partial sums).
There exists a combinatoric formula for this problem. The problem of finding the solutions to your problem is equivalent to finding the number of solutions of the equation
x1 + x2 + x3 + ... + xm = n
where xi < ci
Which is equivalent to finding the cofficient of x^n in the following equation
(1+x+..x^c1)(1+x+..+x^c2)...(1+x+...+x^cm)
The recursion for this equation is pretty simple
M(i,j) = summation(M(i-1, j-k)) where 0<= k <= cj
M(i,j) = 0 j <= 0
M(i,1) = i given for every 1= 1
M(i,j) is the number of ways of distributing the j balls in first i bins.
For the Dynamic Programming part Solve this recursion by Memoization, You will get your DP Solution automatically.