1 条题解

  • 0
    @ 2025-5-19 8:22:29

    题意分析

    题目给定两个整数 K 和 M,要求在 1 到 N(N 需确定)的整数集合里,将所有数字按字典序排序后,K 正好排在第 M 位,需找出满足条件的最小 N;若不存在这样的 N,则输出 0。其中 K 和 M 的范围是 1 到 10 亿,需要考虑高效算法处理。

    解题思路

    前缀计数:字典序排序和数字前缀有关,先定义函数,统计 1 到 N 范围内,字典序小于等于 K 的数字个数,即 K 在字典序中的位置。计算时将 K 转成字符串,依次枚举其所有前缀,统计每个前缀对应数字的数量。

    二分查找:K 是 N 的下界,上界设为较大数,通过二分查找在这个范围内找 N。每次取中间值 mid,用前缀计数函数判断 K 在 1 到 mid 字典序中的位置,若位置等于 M,尝试找更小的 N;若小于 M,说明 N 小了,增大下界;若大于 M,说明 N 大了,减小上界 。 结果输出

    代码

    二分查找结束后,若没找到合适的 N,输出 0;找到则输出最小的 N。

    #include <string>
    using namespace std;
    
    typedef long long LL;
    
    // 将字符串转换为LL类型,替代stoll
    LL strToLL(const string& s) {
        LL res = 0;
        for (size_t i = 0; i < s.length(); ++i) {
            res = res * 10 + (s[i] - '0');
        }
        return res;
    }
    
    // 将LL类型转换为字符串,替代to_string
    string llToString(LL num) {
        if (num == 0) return "0";
        string res;
        bool isNegative = num < 0;
        if (isNegative) num = -num;
        while (num > 0) {
            res = char(num % 10 + '0') + res;
            num /= 10;
        }
        if (isNegative) res = '-' + res;
        return res;
    }
    
    LL count_lex(LL N, const string& K_str) {
        LL res = 0;
        int len = K_str.length();
        string prefix;
        for (int i = 1; i <= len; ++i) {
            prefix = K_str.substr(0, i);
            LL p = strToLL(prefix);
            if (p > N) continue;
            LL power = 1;
            for (int j = 0; j < len - i; ++j) power *= 10;
            res += (p == strToLL(K_str.substr(0, i)) ? 1 : 0) * power;
        }
        return res;
    }
    
    LL find_min_N(LL K, LL M) {
        string K_str = llToString(K);
        LL low = K, high = 1e18;
        LL res = 0;
        while (low <= high) {
            LL mid = (low + high) / 2;
            LL c = count_lex(mid, K_str);
            if (c == M) {
                res = mid;
                high = mid - 1;
            } else if (c < M) {
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return res;
    }
    
    int main() {
        LL K, M;
        cin >> K >> M;
        LL N = find_min_N(K, M);
        cout << N << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    1172
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    3
    已通过
    1
    上传者