A 不同盒子中 N 个相同球的组合

发布于 2024-12-14 20:35:25 字数 567 浏览 3 评论 0原文

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;
}

你好! 在此处输入图像描述

示例:

在此处输入图像描述

这是算法,但花费了很多时间。 也许您知道解决这个问题的更快方法?非常感谢,也很抱歉让您担心。

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!
enter image description here

Example:

enter image description here

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗喜 2024-12-21 20:35:25

你需要的是动态规划。您需要记住函数 f 的那些已计算过的参数的值。也可以不使用递归来实现,如下所示:

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];
}

这只是简单的技术演示。可以再优化一次,可以预先计算t-sum并消除l的循环。而且你不必存储整个表q,你只需要两层,这会减少内存使用。所以结果将如下所示:

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];
}

所以最终需要 O(a*n) 时间来计算。

PS:请注意,答案可能是一个巨大的数字,可能会溢出任何本机整数类型。

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.

揪着可爱 2024-12-21 20:35:25

首先,如果 A*X A*X A*X A*X A*X A*X N,没有办法分配球,所以你可以早点停下来。如果A*X == N,那么只有一种方法。那么首先选择放置 X 球的盒子数量并以较小的限制重复出现可能会更快。

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;
}

如果您经常调用 f,那么为二项式系数创建一个表可能会很有用。

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.

羁绊已千年 2024-12-21 20:35:25

看看 http://www.mathpages.com/home/kmath337.htm 和公式在页面底部。

look at http://www.mathpages.com/home/kmath337.htm and the formula at the bottom of the page.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文