Educational Codeforces Round 121 (Rated for Div. 2)——B - Minor Reduction

B - Minor Reduction

题源:https://codeforces.com/contest/1626/problem/B

题意

给定一个超级大的整数 x ,可以对任意相邻两位数进行操作(把他们拿出来,然后再把他们的和放回原来的位置,注意不能有前导0,也就是说如果和是一位数的话就只放入一位数),求经过一次操作后的最大 x 为多少

思路

我的做法可能太绕了,特判了好多个。

  1. 首先特判掉只有两位数的情况(10 =< x < 100 ),直接加起来就行

  2. 一般情况:

  • 先来分析一下,如果相邻两位加起来能够进位的话,也就是结果还是两位数,对原 x 带来的影响是最小的,又因为和一定比原来两个数字小,所以我们优先对后面的位数来操作。

  • 如果不能进位,放在前面比较好,因为加起来所得到的值一定比原来两位上任何一个数大。比如123(33比15大)

那么就来实现一下:

统计每两个相邻数之和,存在cnt数组里面,记录一个最大的和maxn。对于当前的cnt[i],可以分为两种:

  1. 小于10(不进位的情况):只记录maxn

  2. 大于10(进位):越往后越好,记录下标 k 和 maxn

 对于maxn:

  1. maxn < 10:两数相加一定会比原来任何一位都大,高位数上的改变所增大的值一定比低位数上带来的影响大,所以要在前面改变(比如111,112)

  2. maxn >= 10:两数相加一定会变小,所以尽可能取低位数上来改变(如17878)

我滴代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
const int N = 2e5 + 5;
int t;



int main (){
    cin >> t;
    while (t --){
        string s;
        cin >> s;
        if (s.size() == 2){
            cout << (s[0] - '0') + (s[1] - '0') << endl;
            continue;
        }
        int cnt[N] = {0}, maxn = -1, k = -1;
        for (int i = 1; i < s.size(); i ++){
            cnt[i] = (s[i] - '0') + (s[i - 1] - '0');
            if (cnt[i] < 10){
                if (cnt[i] > maxn)
                    maxn = cnt[i];
            }
            else{
                k = i, maxn = cnt[i];
            }
        }
        if (maxn < 10)
            s[0] = char(cnt[1] + '0'), s[1] = '#';
        else
            s[k] = char(maxn % 10 + '0'), s[k - 1] = char(maxn / 10 + '0');
        for (int i = 0; i < s.size(); i ++)
            if (s[i] != '#')
                cout << s[i];
        cout << endl;
    }
}
//考虑两个可能会被hack掉的数:111, 17878, 112, 291


辛辛苦苦调了好久的代码,码了好久的字啊www

posted @ 2022-03-19 16:34  Sakana~  阅读(42)  评论(0编辑  收藏  举报