一.
试题编号: 201712-1
试题名称: 最小差值
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
给定n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值。
输入格式
输入第一行包含一个整数n。
第二行包含n个正整数,相邻整数之间使用一个空格分隔。
输出格式
输出一个整数,表示答案。
样例输入
5
1 5 4 8 20
样例输出
1
样例说明
相差最小的两个数是5和4,它们之间的差值是1。
样例输入
5
9 3 6 1 3
样例输出
0
样例说明
有两个相同的数3,它们之间的差值是0.
数据规模和约定
对于所有评测用例,2 ≤ n ≤ 1000,每个给定的整数都是不超过10000的正整数。
思路简单: 差值最小只能是大小相邻的两个数, 因此排序, 然后找出相邻差值最小. O(nlgn + n).
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int n, x;
vector<int> v;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> x;
v.push_back(x);
}
sort(v.begin(), v.end());
int m = 10000000;
for (int i = 0; i < (int)v.size() - 1; ++i) {
m = min(m, abs(v[i] - v[i+1]));
}
cout << m;
}
二.
试题编号: 201712-2
试题名称: 游戏
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,……,1号小朋友坐在n号小朋友的顺时针方向。
游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
例如,当n=5, k=2时:
1号小朋友报数1;
2号小朋友报数2淘汰;
3号小朋友报数3;
4号小朋友报数4淘汰;
5号小朋友报数5;
1号小朋友报数6淘汰;
3号小朋友报数7;
5号小朋友报数8淘汰;
3号小朋友获胜。给定n和k,请问最后获胜的小朋友编号为多少? 输入格式 输入一行,包括两个整数n和k,意义如题目所述。 输出格式
输出一行,包含一个整数,表示获胜的小朋友编号。 样例输入 5 2 样例输出 3 样例输入 7 3 样例输出 4 数据规模和约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。
我给出两种方法.
法一: 模拟链表, 还剩最后一个结点就是结果
法二: 使用vector, 当size = 1时, 剩下的值就是结果.其实内部还是用了链表.
法三: 约瑟夫环也可以用数学方法解答, 不过此题并非标准约瑟夫环问题, 而是对条件进行了一些调整.
代码量: 一 > 二 > 三
法一代码:
#include <iostream>
using namespace std;
struct Node {
int val;
Node *last, *next;
};
int n, k;
bool out(int x)
{
if (x % k == 0 || x % 10 == k) return 1;
else return 0;
}
int main()
{
cin >> n >> k;
Node *l1 = new Node;
l1->val = 1;
Node *p = l1;
for (int i = 2; i <= n; ++i) {
Node *tmp = new Node;
tmp->val = i;
p->next = tmp;
tmp->last = p;
p = tmp;
}
p->next = l1;
l1->last = p;
Node *b = l1;
int t = 1;
while (b->next != b) {
if (out(t++)) {
Node *tmp = b->next;
b->last->next = b->next;
b->next->last = b->last;
b = tmp;
}else b = b->next;
}
cout << b->val;
}
法二代码:
#include <iostream>
#include <vector>
using namespace std;
int n, k, t = 0;
bool out(int x)
{
if (x % k == 0 || x % 10 == k) return 1;
else return 0;
}
int main()
{
vector<int> v;
cin >> n >> k;
for (int i = 1; i <= n; ++i)
v.push_back(i);
vector<int>::iterator it = v.begin();
while (v.size() != 1) {
t++;
if (out(t)) v.erase(it);
else it++;
if (it == v.end()) it = v.begin();
}
cout << *it;
}
值得注意的是, erase函数删除某个结点之后, 迭代器自动指向这个结点的后一个结点.
法三代码:
#include <iostream>
using namespace std;
int main()
{
int n, k, ans = 0;
cin >> n >> k;
for (int i = 2; i <= n; ++i)
ans = (ans + k) % i;
cout << ans + 1;
}