1 条题解

  • 0
    @ 2026-10-31 17:57:26

    思路

    题意:每次给出一个长度为 10、只含小写字母的串 ss 和整数 KK,把“合法刻印”按字典序从小到大排列(aaaaaaaaaa 最小、zzzzzzzzzz 最大),修补就是在这个序列上向后移动 KK 步;若移动后越界输出 -1,否则输出新的 10 字母串。输入有多组,读到文件结束。

    把刻印看成 26 进制数

    长度为 10、每位取 a~z 的串,与区间 [0,2610−1][0, 26^{10}-1] 内的整数一一对应(a 记 0,z 记 25)。字典序与数值大小一致,因此“向后移动 KK 步”就是给这个整数加上 KK。

    • 编码:res = res * 26 + (s[i] - 'a'),从高位到低位逐位累加;
    • 最大合法值:up = 26^10 - 1,代码中用同样的方式累加 'z' - 'a' = 25 得到;
    • 越界判定:res + K > up 时无解,输出 -1。

    注意 2610−1≈1.4×101426^{10}-1 \approx 1.4\times10^{14},而 K≤1018K \le 10^{18},加法结果仍在 long long 范围内(<9.2×1018< 9.2\times10^{18}),不会溢出,所以可以直接整数比较,不需要先判断 KK 是否过大。

    解码

    得到新值 res 后,从最高位 i=9i=9 到最低位 i=0i=0 依次确定每一位:

    • 该位权重为 26i26^i,这一位的数字就是 ⌊res/26i⌋\lfloor res / 26^i \rfloor;
    • 代码用 while (res >= sum) { res -= sum; j++; } 做减法计数,等价于上面的除法取整,并同时把余数留在 res 中供低位使用;
    • 因为越界检查保证了 res≤2610−1res \le 26^{10}-1,所以每一位得到的 j 都在 [0,25][0, 25] 内,加上 'a' 就是合法字母。

    powl(26, i) 返回 long double 再赋给整型。269≈5.4×1012<25326^9 \approx 5.4\times10^{12} < 2^{53},可以被浮点数精确表示,因此这里不会有精度误差。

    复杂度

    每组数据只需一次 O(10)O(10) 的编码、一次比较和最多 10×2510 \times 25 次减法,时间 O(1)O(1),空间 O(1)O(1)。

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define dd double
    #define str string
    #define el cout << '\n'
    #define re return
    #define ff first
    #define ss second
    #define pll pair<int,int>
    #define pdd pair<dd,dd>
    #define all(x) x.begin(),x.end()
    #define pb push_back
    using namespace std;
    
    str s;
    int K;
    void go(){
        int res = 0;    // 当前刻印对应的 26 进制数值(a=0 ... z=25)
        int up = 0;     // 最大合法值,即 zzzzzzzzzz 对应的数值 26^10 - 1
        for(int i=0;i<10;i++){
            res = res*26 + s[i]-'a';
            up = up*26 + 'z'-'a';
        }
    
        res += K;       // 向后移动 K 步
        if(res> up){    // 越界:移动后的刻印不存在
            cout<<-1;el;re;
        }
    
        // 按 26 进制从高位到低位还原字符
        str ans = "";
        for(int i=9;i>=0;i--){
            int sum = powl(26, i);  // 第 i 位的权重 26^i(在 double 精度内精确)
            int j = 0;
            while (res >= sum)      // 减法计数,等价于 res / sum 取整
            {
                res -= sum;
                j++;
            }
            ans += (j+'a');
            
        }
        cout<<ans;el;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);cout.tie(nullptr);
        int _=1;
        // 本题为多组数据且不先给出 T,故用 EOF 控制循环,不读组数
        while(cin>>s>>K){
            go();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    42
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者