Posted on 

C++循环结构编程题:寻找兄弟数

题目:如果两个不同的正整数,他们的和是他们的积的因子,就被成为兄弟数。小的是弟数,大的是兄数。
先后输入正整数 n 和 m (n < m),请在 n 至 m-n+1 个数中,找出一对兄弟数。

  1. 如果找不到,输出”No”
  2. 如果找到多对,则找出和最小的一对。
  3. 如果有多对和相等的,则找出弟数最小的那一对。

思路:

枚举每一对不同的数,使用变量a,b记录“当前”的兄弟数,当符合兄弟数的数对出现时,则替换a,b的值。

思考过程中遇到的一个错误的方向就是 枚举【全部】的可能——如果枚举全部的数对,再一一列举比较,就过于麻烦了。因为题干要求的仅仅是一个符合要求的数对,因此所有语句应面向这个要求:例如当遍历到两个值,其和已经大于另一个数对,则不难看出其不可能符合“和最小”的要求,则直接舍弃。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<stdio.h>
#include<iostream>

int main(void) {
int n,m;
scanf("%d %d", &n,&m);
int min = m+1; // 这样后面第一次执行就必然刷新min与max的值;同时,如果min的值不变,则意味着没有符合的兄弟数
int max = n-1;
int amount_min = 2 * m;
for (int i=m; i>n; --i) {
for (int j=i-1; j>=n; --j) {
if (i+j>max+min) break; // 由于最终结果一定是和最小的,因此若当前取的数对和大于“当前”兄弟数,则可以直接跳出循环
if ((i*j)%(i+j)==0) {
int amount = i + j;
// 基于前面的判断,此处amount必小于或等于amount_min
if (amount == amount_min) {
if (j<min) {
min = j;
max = i;
amount_min = amount;
}
}
else {
amount_min = amount;
min = j;
max = i;
}
}
}
}
if (min == m+1 && max == n-1) {
printf("No");
}
else {
printf("%d %d %d", max, min, amount_min);
}
}