从穷举法到插板法:Python解决求和为12的正整数组合20240619

从穷举法到插板法:Python解决求和为12的正整数数学问题

在这篇博客中,我们将使用Python来解决一个有趣的小学数学问题:求出所有正整数组合,使得这些数的和为12。我们将演示如何找到这些组合,并计算每个组合的排列数,最终得到所有可能的排列组合数。

问题描述

我们的问题是找到所有满足 (a + b + c + d = 12) 的正整数组合,并计算每个组合的排列数。我们将展示完整的过程,包括如何找到所有组合,计算每个组合的排列数,并汇总最终结果。

解题思路2:插板法
把 12 看成 12 个 1,12 个 1 之间有 11 个间隔,要把 12 分成 4 个正整数的和,相当于在 11 个间隔中插入 3 个隔板,所以共有组合数 𝐶(11,3)=165。

from math import comb
n = 12
k = 4
combinations_count = comb(n - 1, k - 1)
print(f"Using the stars and bars method, the total number of unique combinations is: {combinations_count}")

结果
Using the stars and bars method, the total number of unique combinations is: 165

解题思路2:穷举法

我们将使用Python的两个步骤来解决这个问题:

  1. 找到所有满足条件的组合。
  2. 计算每个组合的排列数。

步骤1:找到所有组合

组合数的思考:考虑到每个变量至少为1,因此直接开始分配剩余的8个单位。
一个变量为8:如 (8, 0, 0, 0) => (9, 1, 1, 1)
一个变量为7:如 (7, 1, 0, 0) => (8, 2, 1, 1)
一个变量为6:如 (6, 2, 0, 0) => (7, 3, 1, 1)
依此类推直到 (2, 2, 2, 2) => (3, 3, 3, 3)
总共15种情况:通过系统的分配,可以得到15种组合

我们使用itertools库中的combinations_with_replacement函数来生成所有可能的组合。

from itertools import combinations_with_replacement

def find_solutions(n, k):
    solutions = set()
    for combo in combinations_with_replacement(range(1, n), k):
        if sum(combo) == n:
            solutions.add(tuple(sorted(combo)))
    return solutions

n = 12
k = 4
solutions = find_solutions(n, k)
solutions_list = sorted(solutions)

print(f"Total number of unique combinations: {len(solutions_list)}")
print("Combinations:")
for combination in solutions_list:
    print(combination)

运行结果:

Total number of unique combinations: 15
Combinations:
(1, 1, 1, 9)
(1, 1, 2, 8)
(1, 1, 3, 7)
(1, 1, 4, 6)
(1, 1, 5, 5)
(1, 2, 2, 7)
(1, 2, 3, 6)
(1, 2, 4, 5)
(1, 3, 3, 5)
(1, 3, 4, 4)
(2, 2, 2, 6)
(2, 2, 3, 5)
(2, 2, 4, 4)
(2, 3, 3, 4)
(3, 3, 3, 3)

步骤2:计算排列数

接下来,我们计算每个组合的排列数。我们使用math库中的factorial函数来实现这个过程。

from math import factorial
from collections import Counter

def count_permutations(combination):
    counts = Counter(combination)
    denominator = 1
    for count in counts.values():
        denominator *= factorial(count)
    return factorial(len(combination)) // denominator

# 计算每个组合的排列数
permutation_counts = [count_permutations(comb) for comb in solutions_list]

# 统计每个排列数出现的次数
counter = Counter(permutation_counts)

# 生成输出表达式
output_parts = [f"{count}x{permutation_counts.count(count)}" for count in set(permutation_counts)]

# 计算总排列数
total_permutations = sum(permutation_counts)

output_expression = " + ".join(output_parts)

print(f"\nTotal number of unique solutions: {total_permutations}")
print("Detailed calculation:")
print(output_expression)

print("\nEach combination with its permutation count:")
for combination, perm_count in zip(solutions_list, permutation_counts):
    print(f"{combination} - {perm_count} permutations")

运行结果:

Total number of unique solutions: 165
Detailed calculation:
4x2 + 12x8 + 24x2 + 6x2 + 1x1

Each combination with its permutation count:
(1, 1, 1, 9) - 4 permutations
(1, 1, 2, 8) - 12 permutations
(1, 1, 3, 7) - 12 permutations
(1, 1, 4, 6) - 12 permutations
(1, 1, 5, 5) - 6 permutations
(1, 2, 2, 7) - 12 permutations
(1, 2, 3, 6) - 24 permutations
(1, 2, 4, 5) - 24 permutations
(1, 3, 3, 5) - 12 permutations
(1, 3, 4, 4) - 12 permutations
(2, 2, 2, 6) - 4 permutations
(2, 2, 3, 5) - 12 permutations
(2, 2, 4, 4) - 6 permutations
(2, 3, 3, 4) - 12 permutations
(3, 3, 3, 3) - 1 permutation

可视化结果

为了更好地展示每个组合的排列数及其频率,我们使用matplotlib生成一个条形图。这样可以直观地看到每个组合的排列数。

import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用SimHei字体
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

# 数据
labels = [str(combination) for combination in solutions_list]
counts = permutation_counts

# 创建条形图
plt.figure(figsize=(15, 8))
plt.barh(labels, counts, color='skyblue')
plt.xlabel('排列数')
plt.ylabel('组合')
plt.title('每个组合的排列数')
plt.grid(axis='x', linestyle='--', alpha=0.7)
for index, value in enumerate(counts):
    plt.text(value, index, str(value))
plt.tight_layout()

# 保存为图片
plt.savefig('permutation_counts.png', dpi=300, bbox_inches='tight')
plt.show()

通过生成的条形图,可以直观地看到每个组合的排列数,并理解每个组合在总排列数中的贡献。

总结

穷举法在解决复杂问题时非常有用,特别是在没有明确数学模型的情况下。其关键在于有一个清晰的规划和分类思路,确保所有可能性都被考虑到且不重复、不遗漏。在这篇博客中,我们展示了如何使用Python解决一个小学数学问题,并通过组合和排列的方法找出所有满足条件的组合及其排列数。这不仅帮助孩子们更好地理解数学问题,还展示了计算机编程在解决实际问题中的强大能力。

通过这篇博客,我们探索了两种不同的解题思路:穷举法和插板法。穷举法通过系统地枚举所有可能的组合来找到答案,而插板法则通过巧妙的数学转化快速解决问题。这两种方法展示了数学问题的多样性和灵活性,帮助孩子们学到多种解题技巧,培养他们的创造力和思考能力。

无论是直接的穷举法,还是巧妙的插板法,每种方法都有其独特的价值和应用场景,鼓励孩子们在解决问题的过程中不断创新和思考。

希望这篇博客对您有所帮助。如果有任何问题或建议,欢迎留言讨论。

完整代码

以下是完整的Python代码,包含了所有步骤和可视化部分:

from itertools import combinations_with_replacement
from math import factorial
from collections import Counter
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

def find_solutions(n, k):
    solutions = set()
    for combo in combinations_with_replacement(range(1, n), k):
        if sum(combo) == n:
            solutions.add(tuple(sorted(combo)))
    return solutions

def count_permutations(combination):
    counts = Counter(combination)
    denominator = 1
    for count in counts.values():
        denominator *= factorial(count)
    return factorial(len(combination)) // denominator

# 参数
n = 12
k = 4

# 找到所有组合
combinations = find_solutions(n, k)
combinations_list = sorted(combinations)

print(f"Total number of unique combinations: {len(combinations_list)}")
print("Combinations:")
for combination in combinations_list:
    print(combination)

# 计算每个组合的排列数
permutation_counts = [count_permutations(comb) for comb in combinations_list]

# 生成输出表达式
output_parts = [f"{count}x{permutation_counts.count(count)}" for count in set(permutation_counts)]

# 计算总排列数
total_permutations = sum(permutation_counts)

output_expression = " + ".join(output_parts)

print(f"\nTotal number of unique solutions: {total_permutations}")
print("Detailed calculation:")
print(output_expression)

print("\nEach combination with its permutation count:")
for combination, perm_count in zip(combinations_list, permutation_counts):
    print(f"{combination} - {perm_count} permutations")

# 创建条形图展示每个组合及其排列数
plt.figure(figsize=(15, 8))
x_labels = [str(combination) for combination in combinations_list]
y_values = permutation_counts

plt.barh(x_labels, y_values, color='skyblue')
plt.xlabel('排列数')
plt.ylabel('组合')
plt.title('每个组合的排列数')
plt.grid(axis='x', linestyle='--', alpha=0.7)
for index, value in enumerate(counts):
    plt.text(value, index, str(value))
plt.tight_layout()

# 保存为图片
plt.savefig('permutation_counts.png', dpi=300, bbox_inches='tight')
plt.show()

请添加图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Narutolxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值