整数划分为多数之和

题目简述

将整数n,划分为m个整数的和 ( 1 ≤ m ≤ n ) (1 \le m \le n) (1mn),求有多少种加法结果。

  • 额外条件: 整数的顺序也影响结果。

解决方案

解法一、枚举

思考

联想到抽屉原理

  • 将整数n理解为有n个item,将枚举过程理解为,将n个item放到m个抽屉中

  • 现在的问题就在于如何分配item?

容易得出,两种极端情况。

  1. m = n m = n m=n抽屉数等于item个数,这意味着只有一种分法
  2. m = 1 m = 1 m=1,只有一个抽屉,怎么分都也是只有一种分法

那么,就剩下一种最一般的情况了。

  1. n > m n > m n>m, 抽屉的个数小于item个数
    思路:先给每个抽屉都派一个item,盈余的item数surplus为 n − m n - m nm,
    然后,将surplus按照其公因数分配到抽屉中(那么k个公因数也就有k种抽屉分配情况),构造出所有的抽屉,再计算所有抽屉的组合数之和,即计算结果。
  • 注意:对于由于 n > m n > m n>m 即使是加上盈余也存在越界的可能,而且某些情况下会产生重复,那么我们可以规定份数乘以抽屉数不能小于盈余来避免。

python代码实现:

from itertools import permutations


# 计算排列组合个数
def combines(_set):
    return len(set(permutations(_set, len(_set))))


def get_cnt(_desk, _num):
    if _num < 0 or _desk < 0: 
        return 0
    if _desk == 1 or _desk == _num:  # 两种特殊的情况
        return 1
    cnt = 0  # 累计当前所有排列可能
    surplus = _num - _desk  # 给每个抽屉分配一个item后的盈余的个数
    shares = (x for x in range(1, surplus + 1) if surplus <= x * _desk)  # 盈余个数的可划分份数集
    # 根据每次放入不同的份数,构造不同的抽屉
    for x in shares:
        tmp = surplus
        drawers = [1] * _desk  # 生成抽屉并向每个抽屉放入一个item
        index = 0
        while tmp > 0:
            if tmp < x:  # 剩余的盈余数少于单份放入抽屉的数量
                drawers[index] += tmp
                tmp = 0
            else:
                drawers[index] += x
                tmp -= x
            index += 1
        cnt += combines(drawers)  # 计算序列组合数
    return cnt


def solution():
    cnt = 0
    n = int(input("请输入整数n:"))
    for i in range(1, n + 1):
        cnt += get_cnt(i, n)

    return cnt


print(solution())


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值