题目描述

输入输出样例
输入 #1
10 
4 
输出 #1
9 
说明/提示
注:吃掉的果子依次为 3,8,5(回到下面重做第 3 跳),9(回到下面重做第 4 跳)。
写着感觉好别扭
感觉和字符串没啥关系。。
然后洛谷那里的这个有问题:

第三跳吃的是编号5的果子
思路:
我的想法是定义一个int数组,初始化为1,表示有果子,0表示没果子。
循环m次,每次循环先计算每次跳多远,即代码中的jump;
然后判断从当前位置pos加上跳的距离jump是否跳得超过了n,超过了就回到初始位置,也就是pos=1;
最重要的来了,我们不能一下跳jump那么远,得一步一步跳,遇到被吃掉的果子,也就是int数组为0,那么这一步不算,重新跳。
代码1:(数组)
#include<iostream>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    int array[300];
    fill(array, array + n, 1);
    int cnt = 1, pos = 1, jump;
    while (m--) {
        jump = (cnt*cnt*cnt)%5 + 1;
        cnt++;
        if (pos + jump > n) {
            pos = 1;
        }
        int i;
        for (i = pos+1;1; i++) {//不能一下跳jump那么远,得一步一步跳
            if (array[i]) {
                jump--;
            }
            if (!jump) {
                break;
            }
        }
        array[i] = 0;
        pos = i + 1;
    }
    cout << pos-1 << endl;
    return 0;
} 
 
代码2:(链表)
因为这道题涉及到了结点的删除,如果数据量大的话,使用数组会花费很多时间在数据的移动上,所以用的链表。
但是这道题不能用循环链表,因为如果松鼠会跳出这串果子的最前面,它吃不到任何果子时,要回到第一个位置,重新跳;如果是循环链表的话,会计算当前位置到末尾的位置,算到跳跃的步数里。
#include<iostream>
using namespace std;
struct List {
    int data;
    List* next;
};
int main()
{
    int n, m;
    cin >> n >> m;
    List * rear=NULL;
    List* head = (List*)malloc(sizeof(List));
    head->data = -1;
    head->next = NULL;
    for (int i = n; i >= 1; i--) {
        List* newNode = (List*)malloc(sizeof(List));
        newNode->data = i;
        newNode->next = NULL;
        newNode->next = head->next;
        head->next = newNode;
    }
    int jump, cnt;
    List* p = head->next, *pre = NULL;
    for (int i = 1; i <= m; i++) {
        jump = (i * i * i) % 5 + 1;
        cnt = jump;
        while (cnt--) {
            if (p->next == NULL) {
                p = head->next;
                cnt = jump;
                continue;
            }
            pre = p;
            p = p->next;
        }
        if (i != m) {
            pre->next = p->next;
            p = p->next;
        }
    }
    cout << p->data << endl;
    return 0;
} 
 
代码3:(数组模拟链表)
用数组fa[]和数组son[]实现模拟双向链表
对于skip函数里面的for循环,它退出只有两种情况,s为0或者pos为0,当s为0时表示没跳到末尾,正常进行删除;如果pos为0,说明跳到了末尾,这时候需要返回开始的地方重新跳。
#include<iostream>
#define MAX 300
using namespace std;
int fa[MAX], son[MAX], n, m, pos = 1;
void skip(int s) {
    for (; s && pos; s--, pos = fa[pos]);
}
void del(int x) {
    pos = fa[x];
    fa[son[x]] = fa[x];
    son[fa[x]] = son[x];
    fa[x] = son[x] = -1;
}
int main()
{
    cin >> n >> m;
    fa[1] = 2;
    son[n] = n - 1;
    for (int i = 2; i < n; i++) {
        fa[i] = i + 1;
        son[i] = i - 1;
    }
    for (int i = 1; i <= m; i++) {
        int s = (i * i * i) % 5 + 1;
        skip(s);
        if (!pos) {
            pos = 1;
            skip(s);
        }
        if (i == m) {
            cout << pos << endl;
            return 0;
        }
        del(pos);
    }
    return 0;
} 
 
 
代码4:(vector容器实现动态数组)
其实就是用数组,然后删除,移动,不过vector数组的erase方法帮我们实现了移动
#include<iostream>
#include<vector>
#define MAX 300
using namespace std;
int main()
{
    int m, n;
    cin >> n >> m;
    
    vector<int> v;
    for (int i = 1; i <= n; i++) {
        v.push_back(i);
    }
    int jump, pos = 1;
    for (int i = 1; i <= m; i++) {
        jump = (i * i * i) % 5 + 1;
        pos += jump;
        if (pos > v.size()) {
            pos = 1;
            pos += jump;
        }
        if (i == m) {
            cout << v[pos-1] << endl;
        }
        v.erase(v.begin()+pos-1);
    }
    return 0;
} 
 
 
 
 
 
                











![[蓝桥杯 2017 省 B] k 倍区间(前缀和枚举/数论优化)](https://img-blog.csdnimg.cn/20200323125755407.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RoZV9aRUQ=,size_16,color_FFFFFF,t_70)






