C++乘法原理——一步一步算总账
困难8好的,这是一篇面向中小学生的C++乘法原理拓展文章,内容在原基础上补充了更多生活例子、代码解释、常见错误和完整示例。
穿衣服、点早餐、写代码——乘法原理帮你算清总方法数
你有没有想过,每天穿衣服、搭配早餐,甚至设置密码锁,背后都藏着一个数学原理?它就是乘法原理。简单说,如果你做一件事要分成几个步骤,每个步骤都有固定种选择,那么总的方案数就是把这些步数的选择数乘起来。
比如早上穿衣服:你有3件上衣、2条裤子。先选上衣(3种),再选裤子(2种)。那么总共有多少种穿法?答案是 3 × 2 = 6 种。为什么是乘法而不是加法?因为每选一件上衣,都可以搭配2条裤子,相当于3个2相加,所以用乘法。
在C++编程里,乘法原理最常用的地方就是嵌套循环。循环嵌套的次数,正好等于各步方法数的乘积。下面我们一步步来看。
1. 什么是乘法原理?从身边例子说起
例子1:早餐搭配
学校食堂早餐:主食有包子、馒头、面包(3种),饮品有牛奶、豆浆(2种)。你如果先选主食,再选饮品,一共有 3 × 2 = 6 种组合。
- 包子 + 牛奶
- 包子 + 豆浆
- 馒头 + 牛奶
- 馒头 + 豆浆
- 面包 + 牛奶
- 面包 + 豆浆
例子2:密码锁
一个三位密码锁,每位数字可以选0~9(共10种)。要打开锁必须猜对三个数字,第一位有10种,第二位有10种,第三位有10种,总共有 10 × 10 × 10 = 1000 种可能。
例子3:掷两个骰子
第一个骰子点数16(6种),第二个骰子也是16(6种)。两个骰子点数组合有 6 × 6 = 36 种。
这些例子都有一个共同点:事情要分步骤完成,每一步的选法彼此独立。总方法数就是把所有步数的方法数乘起来。
2. 乘法原理在C++中的体现:嵌套循环
还记得上面说的“所有两位数”吗?十位有19共9种,个位有09共10种,总共有 9×10 = 90 个两位数。用两层循环就很清楚:
#include <iostream>
using namespace std;
int main() {
cout << "所有两位数:" << endl;
for (int shi = 1; shi <= 9; shi++) { // 第一步:选十位,9种
for (int ge = 0; ge <= 9; ge++) { // 第二步:选个位,10种
cout << shi << ge << " ";
}
}
cout << endl;
return 0;
}
运行结果(部分):
10 11 12 ... 98 99
我们来仔细看看它是怎么工作的:
- 当
shi = 1时,内层循环ge从0跑到9,输出 10, 11, 12, …, 19(共10个数) - 当
shi = 2时,内层循环ge又从头开始输出 20, 21, …, 29(又是10个) - ……
- 直到
shi = 9,输出 90, 91, …, 99
外层循环每执行一次(1种十位选择),内层循环就要完整跑一遍(10种个位选择)。所以总共输出 9 × 10 = 90 个数。这就是乘法原理在代码里的直接翻译。
你也可以把循环次数想象成穿衣服:外层循环是选上衣,内层循环是选裤子。每件上衣搭配所有裤子,最后得到全部搭配。
3. 乘法原理进阶:加条件限制
有时候,步骤之间会有条件,比如“数字不能重复”。这就需要在循环里加一个 if 判断,限制内层循环的取值。
例如:从1、2、3中选出两个数字组成两位数(数字可以重复),就是 3 × 3 = 9 种。代码很简单:
for (int shi = 1; shi <= 3; shi++) { // 十位:3种
for (int ge = 1; ge <= 3; ge++) { // 个位:3种
cout << shi << ge << " ";
}
}
如果要求数字不能重复,那么十位选完后,个位只能从剩下的两个里选。代码可以这样写:
for (int shi = 1; shi <= 3; shi++) { // 十位:3种
for (int ge = 1; ge <= 3; ge++) { // 个位:3种,但要用条件过滤
if (ge != shi) { // 个位不能等于十位
cout << shi << ge << " ";
}
}
}
这个例子告诉我们:乘法原理的“分步”计算,实际中可能有“不能重复”、“不能同时出现”等限制,需要在循环中加入判断。去掉重复的情况后,总方法数变成了 3 × 2 = 6 种。
4. 新手容易犯的错误
错误1:把乘法当成加法
有的同学看到“先选上衣,再选裤子”,觉得上衣3种、裤子2种,总共有 3 + 2 = 5 种。这是错的!因为你不是只穿上衣或只穿裤子,而是上衣和裤子搭配,所以要用乘法。
错误2:忘记内层循环要完整执行
在嵌套循环中,内层循环的循环变量必须在每次外层循环开始时重新初始化。如果忘了写 int ge = 0;,用了之前定义过的变量,那么内层循环可能只执行一次就结束了。例如:
int ge;
for (int shi = 1; shi <= 9; shi++) {
for (ge = 0; ge <= 9; ge++) { // 这里ge没有重新声明,但正确做法是重新赋初值0
// 没问题,但必须保证ge每次从0开始
}
}
正确写法是 for (int ge = 0; ...) 这样每次循环都重新定义并赋初值0。
错误3:分步的顺序搞反或忘记某一步
比如要生成一个三位数(百位、十位、个位),如果只写两层循环,就会漏掉一位。一定要确保循环的层数等于步骤数。
错误4:条件放错位置
在“数字不重复”的例子中,如果条件 if (ge != shi) 写在外层循环里,就会错误地跳过整个内层循环。要记住:条件要放在内层循环里面,针对每个内层取值做判断。
5. 完整示例:字母密码生成器
下面是一个完整的程序,用乘法原理生成所有由小写字母 a,b,c,d 组成的两位密码(字母可以重复),并统计总数。
#include <iostream>
using namespace std;
int main() {
char first, second; // 第一位和第二位字母
int count = 0; // 总密码数
cout << "所有两位字母密码(可重复):" << endl;
for (first = 'a'; first <= 'd'; first++) { // 第一步:选第一位,4种
for (second = 'a'; second <= 'd'; second++) { // 第二步:选第二位,4种
cout << first << second << " ";
count++; // 每输出一个,计数加1
}
}
cout << endl;
cout << "总共有 " << count << " 种密码。" << endl; // 4×4 = 16
return 0;
}
运行结果:
所有两位字母密码(可重复):
aa ab ac ad ba bb bc bd ca cb cc cd da db dc dd
总共有 16 种密码。
这里第一字母有4种选择,第二字母也有4种,总方法数 = 4 × 4 = 16,正好对应循环总共执行的次数。
你可以把字母改成数字、颜色、水果名,只要把循环的取值范围改一下就行。乘法原理让编程计数变得简单又直观。
6. 相关知识点指引
乘法原理是组合计数的基础。学完这个,你还可以去了解:
- 加法原理:如果一件事有几种不同的方法,不能同时用,总方法数就是把这些方法数加起来。例如从北京到上海可以坐高铁、飞机、大巴,共3种方式,就是加法。
- 排列与组合:乘法原理可以推算出从一组东西里选出几个并排成一列(排列)或选一堆(组合)有多少种方式。
- 枚举法:在编程中,嵌套循环就是一种枚举——把所有可能的情况都列出来。很多计数问题都可以用这种方法解决。
下次遇到“一个披萨可以选3种饼底、4种酱料、5种配料,请问一共有多少种搭配?”这样的问题,就可以直接用乘法原理:3 × 4 × 5 = 60 种。然后你还能写出对应的嵌套循环来验证呢!
例题精讲
某商场有3种不同颜色的帽子、4种不同款式的T恤、2种不同颜色的裤子。小明要选一顶帽子、一件T恤和一条裤子,一共有多少种不同的搭配?
以下C++代码中,cout语句执行了多少次? for(int i=1; i<=4; i++) for(int j=1; j<=6; j++) cout << i*j;
乘法原理适用于所有需要分步骤完成的事情,无论步骤之间是否相互依赖。
给定数组 int steps[] = {3, 4, 2}; int n = 3; int ways = 1;
for(int i = 0; i < n; i++) {
___
}
cout << ways; // 输出总方法数
请填空使得循环正确计算总方法数。以下函数利用乘法原理计算总方法数,请填空:
int totalWays(int steps[], int n) {
int res = 1;
for(int i = 0; i < n; i++) {
___
}
return res;
}