U363553(读数)题解
junhaowang · · 个人记录
还记得上一篇在去年国庆节写的题解么?时隔一年,我又来写题解啦!也是国庆假期。
原题目链接戳我
这一道题就是一个纯模拟。
但是,在模拟的过程中涉及到了关于下标的许多数学判断。
因此必须要注意许多细节,最好的方法就是手写寻找规律。
以下是此题的大致思路:
- 把每一位数字拆开储存到数组里,方便各种操作。
- 接下来从高位往低位遍历。
-
- 如果不是零,那么直接读出来,并且加上该位的名称(个位不加)。
-
- 如果是零,那么继续往后直到没有零(不能超出当前级),如果在末位不读,否则读成“零”。
-
- 如果正好是当前级的最低位,加上当前级名字(个级不加)。
声明:如果有错误,请您指正,万分感激!
//洛谷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;;
}