蓝桥杯真题:握手问题

#include<iostream>
using namespace std;
int main(){
int sum=0;
for(int i=0 ; i<50 ; i++){
sum += i;
}
int num=0;
for(int i=0 ; i<7 ; i++){
num += i;
}
int result;
result = sum-num;
cout<<result;
return 0;
}
这段代码其实是在计算一个组合数学问题:
第一个循环:sum = 0 + 1 + 2 + … + 49 = 1225
-
这个数在握手问题中,代表 50 个人两两之间都握手 的总次数。因为第一个人握 49 次,第二个人握 48 次(已经和第一个握过,所以要避免重复计算,累加的时候实际上是算的每个人“新”握手的次数,即 49+48+…+1+0 = 1225)。
第二个循环:num = 0 + 1 + 2 + … + 6 = 21
-
这个数代表 7 个人两两之间都握手 的总次数。
减法:result = 1225 – 21 = 1204
-
这对应一个场景:一共有 50 个人,但其中有 7 个人互相之间没有握手。
-
计算逻辑是:先假设 50 个人全部互相握手(1225 次),然后减去那 7 个人之间本来应该发生的握手次数(21 次),剩下的就是实际发生的握手次数。
所以,这段代码计算的最终结果是 1204。
为什么不能直接计算 1+2+…+43?
这个数字对应的是一个完全不同的场景:就43 个人之间握手(甚至不是正确代表43个人之间握手。)
但我们的场景不是这样。我们的场景是:
-
总人数 50。
-
这 50 个人被分成了两组:一组是 43 个“正常人”,另一组是 7 个“小团体”。
-
规则是:“正常人”要和所有人握手(包括另一个“正常人”和所有“小团体”成员),但“小团体”内部成员之间不握手。
所以1+2+…+43 这个公式完全无法描述这个复杂的规则。
把问题分成三类握手:
-
A类: 43 个“正常人”之间的互相握手。
-
B类: 43 个“正常人”与 7 个“小团体”成员之间的握手。
-
C类: 7 个“小团体”成员之间的互相握手。
代码的 1225 – 21 = 1204 这个结果,其实就是 A类 + B类 的握手次数总和。让我们拆开看:
-
A类(43个正常人之间握手): 次数是 1+2+…+42 = 903。(42指的是:1个人与其他42个人握手)
-
B类(43个正常人与7个“小团体”成员握手):
-
每个“正常人”要和 7 个“小团体”成员握手,所以是 43 * 7 = 301 次。
-
-
总数: 903 + 301 = 1204。和代码结果一致!




