如何拆分一个整数Z,使得被拆分的N个数之和为Z,且这N个数在[a,b]之间?

大板牙花生 2015-11-23 08:23:18
加精
如何拆分一个整数Z,使得被拆分的N个数之和为Z,且这N个数在[a,b]之间?
...全文
2142 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
钮牛 2015-12-01
  • 打赏
  • 举报
回复
就是一个算法的问题,找一个算法大全看一下
大板牙花生 2015-12-01
  • 打赏
  • 举报
回复
引用 16 楼 hexingfusaipao 的回复:
现有a,b,Z三个值; 设未知数N;则有z / a = N1,z / b = N2,则N2 <= N <= N1; 接下来就考虑N在N2在N1之间的循环了; for(N = N2;N < N1;N++) 在循环里面取N组Z % N与0之间数字,保证数字之和为Z % N即可;
这个是常规解法。如果这样循环解决的话就没有必要谈论这样的帖子了。。。想寻求更为高效,起码是时间可控的。。。
hexingfusaipao 2015-11-30
  • 打赏
  • 举报
回复
现有a,b,Z三个值; 设未知数N;则有z / a = N1,z / b = N2,则N2 <= N <= N1; 接下来就考虑N在N2在N1之间的循环了; for(N = N2;N < N1;N++) 在循环里面取N组Z % N与0之间数字,保证数字之和为Z % N即可;
wshyhm 2015-11-28
  • 打赏
  • 举报
回复
引用 5 楼 wter26 的回复:
[quote=引用 4 楼 lm_whales 的回复:]
上面不严格,而且有错误
Z要拆分成N份,并且 每份在[a,b] 中
则 必须有 aN <=Z <= bN;
最小可拆分成 a,最大可拆分成 b

这个也并不严格,因为如果前N-1个数字拆分为A的时候,可能导致第N个数字超出了【A,B】的范围。
所以如果综合考虑随机性和范围的话,这是一个非常难计算的算法啊。。。现在我只想到了穷举法。有没有更为高效简便的方法[/quote]
确实有这个可能,不防是拆分的数为 (A+B) / 2.
业余草 2015-11-27
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#include <stdlib.h>
void print(int res[], int num) {
    static int L=0;
    L++;
    printf("%8d:",L);
    for (int i=0;i<num;++i) {
        printf(" %d", res[i]);
    }
    printf("\n");
}
void split(int n, int m) {// n表示总数,m表示最大因子
    static int res[100];// 保存结果
    static int num=-1;// 当前因子下标

    if (n<m || n<0 || m<1) return;
    num++;
    if (0==n) {// 递归终止条件,为0不可再分,直接输出
        print(res,num+1);
        num--;
        return;
    } else {
        if (n==m) {// 不拆,直接输出
            res[num]=m;
            print(res,num+1);
            num--;
        } else {
            // 拆分出第一个
            res[num]=m;
            n=n-m;

            if (m>n) m = n; // 最大因子不可能大于总数

            for (int i=m;i>=1;--i) {// 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
                split(n,i);
            }
            num--;
        }
    }
}
void Split(int n) {
    if (n<=0) return;
    if (100<n) {
        printf("Up to 100\n");
        return;
    }
    for (int i=n;i>=1;--i) {
        split(n, i);
    }
}
void main(int argc,char **argv) {
         if (argc<=1) Split(5);
    else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));
    else              Split(atoi(argv[1]));
}
我认真的看完了
cattpon 2015-11-27
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
仅供参考:
#include <stdio.h>
#include <stdlib.h>
void print(int res[], int num) {
    static int L=0;
    L++;
    printf("%8d:",L);
    for (int i=0;i<num;++i) {
        printf(" %d", res[i]);
    }
    printf("\n");
}
void split(int n, int m) {// n表示总数,m表示最大因子
    static int res[100];// 保存结果
    static int num=-1;// 当前因子下标

    if (n<m || n<0 || m<1) return;
    num++;
    if (0==n) {// 递归终止条件,为0不可再分,直接输出
        print(res,num+1);
        num--;
        return;
    } else {
        if (n==m) {// 不拆,直接输出
            res[num]=m;
            print(res,num+1);
            num--;
        } else {
            // 拆分出第一个
            res[num]=m;
            n=n-m;

            if (m>n) m = n; // 最大因子不可能大于总数

            for (int i=m;i>=1;--i) {// 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
                split(n,i);
            }
            num--;
        }
    }
}
void Split(int n) {
    if (n<=0) return;
    if (100<n) {
        printf("Up to 100\n");
        return;
    }
    for (int i=n;i>=1;--i) {
        split(n, i);
    }
}
void main(int argc,char **argv) {
         if (argc<=1) Split(5);
    else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));
    else              Split(atoi(argv[1]));
}
正解!~感谢分享~
xuzuning 2015-11-27
  • 打赏
  • 举报
回复
伪码: 假定 a <= Z/N <= b 成立 令 r[i[ = a i = 0,1,2....N-1 n = aN while(n) { i = rand(0,N); if(r[i] < b) { r[i]++ n-- } }
qq_33157656 2015-11-27
  • 打赏
  • 举报
回复
恩,可以看看,但是
xuzuning 2015-11-27
  • 打赏
  • 举报
回复
这不就是人们都在讨论的 红包分派 的算法吗? 纯数学推导应该可以,可能比较复杂,但最终还是得落实到代码上的
lm_whales 2015-11-26
  • 打赏
  • 举报
回复
在 aN<=Z<=bN 的条件下: 严格的就是 假设 某一次拆分,最小值为 min ,a=<min <=b 则最大可拆分值为,max = Z - min *(N-1) <=b 这个情况下,可拆分 其实只需要设定最小值,然后拆分即可 因为每个值都比最小值大 所以 只需要拆分 Z-min*N ,然后加上min即可 如果Z < min*N 则不必拆分了,此序列不存在。
lm_whales 2015-11-26
  • 打赏
  • 举报
回复
引用 5 楼 wter26 的回复:
[quote=引用 4 楼 lm_whales 的回复:] 上面不严格,而且有错误 Z要拆分成N份,并且 每份在[a,b] 中 则 必须有 aN <=Z <= bN; 最小可拆分成 a,最大可拆分成 b
这个也并不严格,因为如果前N-1个数字拆分为A的时候,可能导致第N个数字超出了【A,B】的范围。 所以如果综合考虑随机性和范围的话,这是一个非常难计算的算法啊。。。现在我只想到了穷举法。有没有更为高效简便的方法[/quote] 老赵的方法就行了, 只是,不能拆分的就别去强拆了 要考虑范围,最小和最大的不能出界 所以Z-N*a 在拆分就行了,拆完后加上a 一旦拆分的结果超过b 则弃之可也
大板牙花生 2015-11-25
  • 打赏
  • 举报
回复
引用 4 楼 lm_whales 的回复:
上面不严格,而且有错误 Z要拆分成N份,并且 每份在[a,b] 中 则 必须有 aN <=Z <= bN; 最小可拆分成 a,最大可拆分成 b
这个也并不严格,因为如果前N-1个数字拆分为A的时候,可能导致第N个数字超出了【A,B】的范围。 所以如果综合考虑随机性和范围的话,这是一个非常难计算的算法啊。。。现在我只想到了穷举法。有没有更为高效简便的方法
lm_whales 2015-11-24
  • 打赏
  • 举报
回复
上面不严格,而且有错误 Z要拆分成N份,并且 每份在[a,b] 中 则 必须有 aN <=Z <= bN; 最小可拆分成 a,最大可拆分成 b
大板牙花生 2015-11-24
  • 打赏
  • 举报
回复
引用 2 楼 lm_whales 的回复:
t=Z/N 如果 t在 【a,b】中 则是可拆分的,否则无法拆分。 最小可拆分数为 t,可拆分最大数 为 s= max(b, Z-t*(N -1)) 然后 就可拆分了从 t,到 s 拆分 Z了
这个公式不理解啊。能不能讲的详细一点,而且随机性是否支持的并不好
lm_whales 2015-11-23
  • 打赏
  • 举报
回复
t=Z/N 如果 t在 【a,b】中 则是可拆分的,否则无法拆分。 最小可拆分数为 t,可拆分最大数 为 s= max(b, Z-t*(N -1)) 然后 就可拆分了从 t,到 s 拆分 Z了
赵4老师 2015-11-23
  • 打赏
  • 举报
回复
仅供参考:
#include <stdio.h>
#include <stdlib.h>
void print(int res[], int num) {
    static int L=0;
    L++;
    printf("%8d:",L);
    for (int i=0;i<num;++i) {
        printf(" %d", res[i]);
    }
    printf("\n");
}
void split(int n, int m) {// n表示总数,m表示最大因子
    static int res[100];// 保存结果
    static int num=-1;// 当前因子下标

    if (n<m || n<0 || m<1) return;
    num++;
    if (0==n) {// 递归终止条件,为0不可再分,直接输出
        print(res,num+1);
        num--;
        return;
    } else {
        if (n==m) {// 不拆,直接输出
            res[num]=m;
            print(res,num+1);
            num--;
        } else {
            // 拆分出第一个
            res[num]=m;
            n=n-m;

            if (m>n) m = n; // 最大因子不可能大于总数

            for (int i=m;i>=1;--i) {// 循环,第二个因子可以继续拆分,而且按照最大因子不同可以拆分成多个
                split(n,i);
            }
            num--;
        }
    }
}
void Split(int n) {
    if (n<=0) return;
    if (100<n) {
        printf("Up to 100\n");
        return;
    }
    for (int i=n;i>=1;--i) {
        split(n, i);
    }
}
void main(int argc,char **argv) {
         if (argc<=1) Split(5);
    else if (argc>=3) split(atoi(argv[1]),atoi(argv[2]));
    else              Split(atoi(argv[1]));
}

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧