安全密码

#include <bits/stdc++.h>
using namespace std;
#define ll long long  // 定义long long类型简写

int main() {
    string s;  // 存储输入的密码字符串
    cin >> s;  // 读取输入
    
    ll ans = 0;      // 记录总操作次数
    int cntB = 0;    // 统计B操作的累积次数(模10意义下)
    
    // 从字符串末尾向前遍历(逆向处理)
    for (int i = s.size()-1; i >= 0; i--) {
        int t = s[i] - '0';  // 将当前字符转换为数字
        
        // 调整当前数字:考虑之前所有B操作的影响
        // +10是为了避免负数,%10确保在0-9范围内
        t = (t - cntB % 10 + 10) % 10;
        
        // 处理第一个字符(最左边的字符)
        if (i == 0) {
            ans += t;  // 第一个字符只能通过t次B操作得到
        } else {
            // 对于其他位置的字符
            if (t == 0) { 
                ans++;  // 0只需1次A操作(追加0)
            } else {
                // 非0字符需要:t次B操作+1次A操作
                ans += t + 1;
                cntB += t;  // 累计B操作次数
            }
        }
    }
    
    // 输出总操作次数(+1是因为初始空字符串需要一次操作才能开始)
    cout << ans;
    return 0;
}

解题思路:

  1. 逆向思维:从字符串末尾向前处理,这样可以更好地跟踪B操作的影响。

  2. 关键观察

    • 每个B操作会影响字符串中的所有数字
    • A操作只在字符串末尾添加0
    • 最左边的字符只能通过B操作得到
  3. 操作影响计算

    • 对于每个数字,需要减去之前所有B操作的影响(模10)
    • 如果调整后的数字是0,说明只需要1次A操作
    • 如果是其他数字,需要相应次数的B操作和1次A操作
  4. 累积效应

    • 使用cntB记录B操作的总次数
    • 每次B操作的影响会传递到前面处理的字符
  5. 边界情况

    • 第一个字符特殊处理(只能通过B操作)
    • 空字符串需要至少一次操作才能开始

为什么这样计算:

  • 逆向处理:因为B操作会影响所有前面的字符,从后往前可以更容易计算每个字符需要的原始值
  • 模运算:B操作的效果是循环的(0→1→...→9→0),所以用模10处理
  • 操作计数:每个字符的生成要么通过A+B组合,要么直接通过B(对第一个字符)

这个算法的时间复杂度是O(n),其中n是字符串长度,非常高效,适合处理最大5×10^5长度的输入。

posted @ 2025-05-24 21:18  季风起  阅读(11)  评论(0)    收藏  举报