趣味挑战题——7-2 “接肢”葛瑞克(20 分)

31 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

题目描述:

欢迎来到交界之地,褪色者。
恶名昭彰的BOSS“接肢”葛瑞克通过接肢来提升自己的力量,但是最初的葛瑞克十分弱小,接肢数量仅为可怜的1。接下来褪色者会和葛瑞克进行战斗。
假设褪色者面对葛瑞克战败后,再一次挑战葛瑞克时,葛瑞克会在自己原来的身体上通过接肢加强自己的力量,而接肢的数量是以指数递增的。比如褪色者第二次挑战时(假设褪色者不可能第一次就打败葛瑞克),接肢的数量就是第一次的数量 * 2,第三次挑战就是第二次的数量 * 3,以此类推。
褪色者通过攻击来解肢击败葛瑞克,而褪色者的攻击伤害只有质数才会对BOSS造成伤害,合数的攻击对于BOSS无效。且每次攻击伤害都只能从2开始,除非本次攻击无法完全整数解肢(比如接肢数量为21时,伤害为2无法解肢,只有伤害增加到3时才可以攻击BOSS解肢,攻击后接肢数量为7),那么就会伤害增加一点继续攻击BOSS。
当葛瑞克的接肢数量回到最初的起点的时候,即为战胜BOSS。

输入格式:

题目给出褪色者最终战胜葛瑞克所挑战的次数n。

输出格式:

题目要求你输出战胜葛瑞克时,褪色者的攻击的伤害a和伤害a的攻击次数b,a和b之间用空格隔开。并且每一组伤害独占一行输出,且每一行依次递增的输出伤害。

数据范围:

2 ≤ n ≤ 106

输入样例:

5

输出样例:

2 3
3 1
5 1

代码长度限制   16 KB

时间限制     400 ms

内存限制     64 MB

思路分析:

这道题目看起来十分的懵逼,但是细看你会发现,这其实就是让你输入一个数,求1~这个数的所有数的质数和,然后输出这些数的次数

但是肯定不能从1这个数每个数都算一遍,这太麻烦了,所有要用筛法

代码如下:

#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
using namespace std;

const int N = 1e6 + 10;
int cnt, primes[N];
bool st[N];

//素数数组
void getprimes(int n) {
    for (int i = 2; i <= n; i++) {
        if (!st[i]) {
            primes[cnt++] = i;
            for (int j = i; j <= n; j += i) st[j] = true;
        }
    }
}

int main() {
    getprimes(1e6);
    int n;
    cin >> n;
    int cnt = 1;
    int cur = 2;
    int exp = 2;
    int idx = 0;
    map<int, int> mp;
    do {
        if (cur % primes[idx] == 0) {
            cur /= primes[idx];
            mp[primes[idx]]++;
            idx = 0;
        }
        else
            idx++;
        // 如果回到了1,证明被战胜了
        if (cur == 1) {
            cnt++;
            cur = 1;
            // 接肢的数量是以指数递增的
            cur *= (++exp);
        }
    } while (cnt != n);
    // 输出结果
    for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++)
        cout << it->first << " " << it->second << endl;
    return 0;
}

结果如下:

image.png PS:成功解题=理清思路+一定的技巧~