题解
7-1 好数 (15 分)
好数是指由一对正整数按照 这个规则生成的数,a 和 b 就称为这个好数的源头。例如 91 就是一个好数,因为 ,于是数对就是 91 的源头。而对于一个好数,其源头并不一定唯一,例如就是 91 的另一个源头。 本题就要求你编写程序,判断一个给定的数字是否好,并且输出好数的所有源头。
输入格式
输入在第一行给出一个不超过 100 的正整数 N,随后 N 行,每行给出一个不超过 104的正整数。
输出格式
对于每一个输入的数字,如果其是好数,则首先在一行中输出 Yes,然后每行输出它的一个源头,格式为 a b,按 a 的递增顺序输出;否则在一行中输出 No和比该数大的最小的好数,其间以空格分隔,然后每行输出这个好数的一个源头,格式同上。
输入样例
3
1
91
50
输出样例
No 7
1 2
Yes
1 9
5 6
No 52
2 6
思想
我刚开始是这样想的:
t = (i * i) + (i * j) + (j * j);
如果t大于了x(输入的样例值),那么以后i,j再怎么迭代,通过计算都得不到x这个值了,那么就保存一下大于x的值maxn,保存一下此时的i,j,然后退出循环。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
int n;
int flag;
int maxn;
vector<PII>v;
bool cmp(PII a, PII b) {
return a.first < b.first;
}
int main() {
cin >> n;
while (n--) {
flag = 0;
maxn = 0;
int t = 0;
int idx = 0, idy = 0;
int x;
cin >> x;
for (int i = 1; i <= 100; i++) {
for (int j = 1; j <= 100; j++) {
if (i < j) {
t = (i * i) + (i * j) + (j * j);
}
// cout << "t: " << t << endl;
if (t == x) {
flag = 1;
v.push_back({i, j});
} else if (t > x) {
maxn = t;
idx = i, idy = j;
break;
}
}
if (flag == 0)
break;
}
sort(v.begin(), v.end(), cmp);
if (flag) {
cout << "Yes" << endl;
for (auto &it : v) {
cout << it.first << " " << it.second << endl;
}
} else {
cout << "No" << endl;
cout << maxn << endl;
cout << idx << " " << idy << endl;
}
}
return 0;
}
但是这样是错的,就拿第三个样例x=50举例,上面的代码计算出来50不是“好数”。并且大于50的最小“好数”是50,i,j为1,7。
而题目提供的答案是:大于x=50的最小“好数”是52,i,j是2,6。
Debug
如下图所示:
当i=1,j=7的时候,此时t值是57,57虽然大于50,但是此刻我们不能结束循环,把57赋给maxn。
因为我们可以发现i=2,j=6时得到的t值52比57更小,是更满足条件的。
因此我们要把break去掉,加一个min()函数。
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
int n;
int flag;
int maxn;
int cnt;
vector<PII>v;
bool cmp(PII a, PII b) {
return a.first < b.first;
}
int main() {
cin >> n;
while (n--) {
flag = 0;
maxn = 0x3f3f3f3f;
int t = 0;
int idx = 0, idy = 0;
v.clear();
cnt = 1;
int x;
cin >> x;
for (int i = 1; i <= 100; i++) {
for (int j = 1; j <= 100; j++) {
if (i < j)
t = (i * i) + (i * j) + (j * j);
if (t == x) {
flag = 1;
v.push_back({i, j});
cnt++;
} else if (t > x) {
maxn = min(maxn, t);
if (t == maxn) {
idx = i, idy = j;
}
}
}
}
sort(v.begin(), v.end(), cmp);
if (flag) {
cout << "Yes" << endl;
for (auto &it : v) {
cout << it.first << " " << it.second << endl;
}
} else {
cout << "No" << endl;
cout << maxn << endl;
cout << idx << " " << idy << endl;
}
}
return 0;
}