2025年天梯赛补题记录——整数的持续性

图片1-1
为什么没写出来:哈哈,看到400ms就不想写了,被前面一个题目卡了两次时间心态崩了,头脑发昏以为直接算过去会超时(能说那个时候快困死了脑袋很不灵光吗,给自己的无能找借口嘻嘻)
优化思路:
1.记忆化缓存:一想便知道每个数的分解都算一次很费时间,可以联想到记忆化缓存——如果一个数的分解路径上出现了曾经分解计算过的数字,那么直接取用“这个数对应的持续性”即可——显然,这里有一个“映射关系”,unordered_map.
——具体操作:使用vector容器path存储分解路径上的数,得出最后的持续性后,进行路径回溯(遍历path里的数)递推计算路径数对应的持续性,更新记忆化缓存
2.分解操作和乘积操作同时进行,一个迭代分解解决
时间复杂度分析:

AC代码:

点击查看代码
#include <iostream>
#include <unordered_map>  //实现记忆化缓存
#include <vector>//动态存储
#include <algorithm>
using namespace std;

int get_product(int num) {  //边拆数边生成新的数
    int product = 1;
    while (num > 0) {
        int digit = num % 10;  //拆数
        product *= digit;  //新的数
        num /= 10;
    }
    return product;
}

int main() {
    int a, b;
    cin >> a >> b;
    unordered_map<int, int> memo;
    int max_pers = -1;
    vector<int> result;

    for (int n = a; n <= b; ++n) {  //循环处理数
        int current = n;    
        int pers = 0;  //每次循环都会更新为0
        vector<int> path;  //只存放这次计算持续性涉及的数字(注意并非数码)

        while (true) {
            auto it = memo.find(current);  //实际上一开始memo这个映射为空
            if (it != memo.end()) {
                pers += it->second;
                break;
            }  //不懂,先跳过
            if (current < 10) {
                break;
            }  //不用计算其持续性
            path.push_back(current);    //将数放入path动态数组,为什么?
            current = get_product(current);  //新的数
            pers++;  //计算current的数位
        }

        // Update memo with the current path
        int total_pers = pers;  
        for (int i = 0; i < path.size(); ++i) {
            int num = path[i];
            if (memo.find(num) == memo.end()) {
                memo[num] = total_pers - i;  //存放新的中间结果,保证每个数只分解一次,保证记忆性缓存的正确性
            }
        }

        // Update result
        if (pers > max_pers) {
            max_pers = pers;
            result = {n};  //清空结果容器并添加正确结果;初始化操作O(1)
        } else if (pers == max_pers) {
            result.push_back(n);
        }
    }

    // Sort and output
    sort(result.begin(), result.end());
    cout << max_pers << "\n";
    for (size_t i = 0; i < result.size(); ++i) {
        if (i > 0) cout << " ";
        cout << result[i];
    }
    cout << endl;

    return 0;
}

其他题解思路分析与学习:
1.不进行记忆化缓存也ok,除此之外思路相同

posted @ 2025-03-31 16:44  xialingn  阅读(174)  评论(0)    收藏  举报