int f(int n,int a,int x)
{
if(a==1)
{
if(n>=0 && n<=x) //HERE WAS ERROR,sorry
return 1;
else
return 0;
}
int ans=0;
for(int i=0;i<=x;i++)
ans += f(n-i,a-1,x);
return ans;
}
Hello!
Example:
Here is algorithm, but it spends very much time. Maybe you know a faster way to solve this problem? Thanks very much and sorry for worry.
What you need is dynamic programming. You need to memorize values of function f for those arguments for which it already have been calculated. Also it can be implemented without recursion like this:
int f(int n,int a,int x)
{
int q[1000][50]; // to simplify and not use dynamic allocation assume that a < 50 and n < 1000
q[0][0] = 1;
for (int i = 1; i < 1000; ++i)
q[i][0] = 0;
for (int i = 1; i <= a; ++i)
{
for (int j = 0; j <= n; j++)
{
int t = 0;
for (int l = 0; l <= j && l <= x; ++l)
t += q[j - l][i-1];
q[j][i] = t;
}
}
return q[n][a];
}
This is only simple technique demonstration. It can be optimized one more time, you can precalculate t-sum and eliminate loop for l. And you don't have to store whole table q, you only need two layers, it will reduce memory usage. So the result will look like this:
int f(int n,int a,int x)
{
int q[1000][2]; // to simplify and not use dynamic allocation assume n < 1000
q[0][0] = 1;
for (int i = 1; i < 1000; ++i)
q[i][0] = 0;
int current = 1;
for (int i = 1; i <= a; ++i)
{
int t = 0;
for (int j = 0; j <= n; j++)
{
t += q[j][1 - current];
if (j > x)
t -= q[j - x - 1][1 - current];
q[j][current] = t;
}
current = 1 - current;
}
return q[n][1 - current];
}
So finally it will take O(a*n) time to compute.
PS: Note that answer can be a huge number which can overflow any native integer type.
First of all, if A*X < N
, there's no way to distribute the balls, so you can stop earlier. If A*X == N
, there's only one way. Then it's probably faster to first pick the number of boxes in which you place X
balls and recur with a smaller limit.
int f(int n, int a, int x){ // should all be unsigned, actually
if (n == 0){
return 1;
}
int p = a*x;
if (p < n){
return 0;
}
if (p == n){
return 1;
}
if (x == 1){
return binom(a,n); // ways to choose n boxes from a boxes
}
// now the interesting cases
int ways = 0; // should perhaps be unsigned long long, that number grows fast
int xCount, tempRes, min, max;
min = a+n-p;
if (min < 0) min = 0;
max = n/x;
for(xCount = min; xCount <= max; ++xCount){
tempRes = f(n - x*xCount,a - xCount, x-1); // ways to distribute the remaining balls
ways += binom(a,xCount)*tempRes; // multiply by the number of ways to choose xCount boxes
}
return ways;
}
It might be useful to create a table for the binomial coefficients if you call f
often.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With