2017-12CCF认证_1,2题

一.

试题编号: 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;
}

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/80990609
今日推荐