U363553(读数)题解

· · 个人记录

还记得上一篇在去年国庆节写的题解么?时隔一年,我又来写题解啦!也是国庆假期。

原题目链接戳我

这一道题就是一个纯模拟。

但是,在模拟的过程中涉及到了关于下标的许多数学判断。

因此必须要注意许多细节,最好的方法就是手写寻找规律。

以下是此题的大致思路:

声明:如果有错误,请您指正,万分感激!

//洛谷U363553保姆级详解,一看就会!出题人junhaowang的心血!!! 
#include <bits/stdc++.h>
using namespace std;;

string //本题涉及到大量中文拼音,可以用数组先存储一下 
    convert [15] //把一个阿拉伯数字转化成拼音 
        = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"},
    wei [10] //在每个级以内,各个位的数字后面加的字(个位后面不加字) 
        = {"", "shi", "bai", "qian", "wan"},
    ji [8] //每个级后面要加的字(个级不加字) 
        = {"", "wan", "yi"}
;; 

long long //否则真的会爆的!!!我为了这个调好久
    n, //输入的数
    a [17], //把数的每一位都拆开来存进数组,方便处理
    i //临时下标,在拆分后可以表示这个数的位数(一旦拆分出一位就会加一) 
;; 

signed main (void)
{
    ios::sync_with_stdio (false);;
    cin.tie (0), cout.tie (0);;
    cin >> n;; //输入这个数字
    a [0] = 1;; //这个操作主要是为了给后面的关于连续0区间判断来加一个“围栏” 
    while (n) //循环,把这个数字“五马分尸” 
    {
        a [++i] = n % 10;; //存储一下,并且更新位数
        n /= 10;; //把这一位砍掉 
    }
    //这样存储,下标1表示个位,下标2表示十位……以此类推。
    //接下来,我们读数肯定从最高位开始读
    //因此我们就可以利用i了
    signed
        _s //尽管变量名很奇怪,但是凑合凑合吧(这也是遍历下标用的) 
            = i
    ;;
    while (_s >= 1) 
    {
        if (a [_s]) //不是零,就读出来 
        {
            cout << convert [a [_s]];;
            //此时后面要加对应位的字,先减1模4获得在当前级中的位编号
            cout << wei [(_s - 1) % 4];;
        }
        else //如果是0,就需要一直往下走,直到最后一个零。
        //这个连续的0区间,都读作一个字:零!
        {
            while (!a [_s - 1] && _s % 4 != 1) //经过循环之后,_s这个变量会代表连续的最后一个0的下标 
            //特殊地,必须不能超出此级的范围,也就是不能成为模4为1的数 
            {
                _s--;;
            }
            //但是如果在某个级的结尾(也就是模4为1的位置)不读 
            if (_s % 4 != 1)
            {
                cout << convert [0];;
            }
        }
        if (_s % 4 == 1) //如果正好在某个级的末尾,要读出级的名字
        {
            cout << ji [(int) ceil(_s / 4.0) - 1];; //除以4天花板再减去1,就是级的编号
        }
        _s--;; //当然最后,肯定还要遍历到下一位啦 
    }
    return 0;;
}