题解:洛谷 P1781 宇宙总统
【题目来源】
洛谷:P1781 宇宙总统 - 洛谷(luogu.com.cn)
【题目描述】
地球历公元 \(6036\) 年,全宇宙准备竞选一个最贤能的人当总统,共有 \(n\) 个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。
【输入】
第一行为一个整数 \(n\),代表竞选总统的人数。
接下来有 \(n\) 行,分别为第一个候选人到第 \(n\) 个候选人的票数。
【输出】
共两行,第一行是一个整数 \(m\),为当上总统的人的号数。
第二行是当上总统的人的选票。
【输入样例】
5
98765
12365
87954
1022356
985678
【输出样例】
4
1022356
【核心思想】
-
问题分析:有 \(n\) 名候选人,每人的票数是一个可能长达 100 位的大整数。需要找出票数最多的候选人,输出其编号和票数。由于票数可能超出 64 位整数范围,不能直接使用数值比较,必须使用字符串比较:先比较长度(位数多则数值大),长度相同再按字典序比较。
-
算法选择:
- 字符串比较:以字符串形式读入票数。维护当前最大票数字符串
max和对应候选人编号mark。对于每个新读入的字符串s,若s.length() > max.length(),或长度相等且s > max(字典序),则更新max和mark。 - 复杂度:\(O(n \times L)\),其中 \(L\) 是票数的最大长度(\(\le 100\)),\(n\) 为候选人数量。
- 字符串比较:以字符串形式读入票数。维护当前最大票数字符串
-
关键步骤:
- 读入:读取 \(n\),然后循环 \(n\) 次,每次读入一个票数字符串
s。 - 比较与更新:若
s.length() > max.length()或 (s.length() == max.length()且s > max),则更新max = s,mark = i。 - 输出:输出
mark和max。
- 读入:读取 \(n\),然后循环 \(n\) 次,每次读入一个票数字符串
-
时间/空间复杂度:
- 时间复杂度:\(O(n \times L)\),\(L \le 100\)。
- 空间复杂度:\(O(L)\)。
-
大数比较与字符串:
- 位数优先:比较两个大整数时,位数多的必然更大。
- 字典序比较:当位数相同时,字符串的字典序比较等同于数值比较(因为数字字符串长度相同且无前导零)。
- 适用场景:当处理超出基本整数类型的大整数比较时,字符串比较是最简单有效的方法。
【算法标签】
普及- #字符串入门
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int main() {
string max = "0", s; // max: 当前最大的数字字符串,s: 临时存储输入的字符串
int len1, len2, mark = 1, n; // len1: max的长度,len2: s的长度,mark: 最大数字的位置,n: 输入的数字个数
cin >> n; // 输入数字的个数
for (int i = 1; i <= n; i++) {
cin >> s; // 输入一个数字字符串
len1 = max.size(); // 获取当前最大数字字符串的长度
len2 = s.size(); // 获取当前输入数字字符串的长度
// 比较规则:
// 1. 如果当前输入的数字字符串长度更长,则更新最大值和位置
if (len1 < len2) {
mark = i; // 记录当前数字的位置
max = s; // 更新最大值
}
// 2. 如果长度相同,按字典序比较,如果当前输入的数字字符串更大,则更新最大值和位置
else if (len1 == len2 && max < s) {
mark = i; // 记录当前数字的位置
max = s; // 更新最大值
}
}
// 输出结果
cout << mark << endl << max; // 输出最大数字的位置和最大数字
return 0;
}
【运行结果】
5
98765
12365
87954
1022356
985678
4
1022356
浙公网安备 33010602011771号