P8115 题解
Jerrlee✅
2022-02-09 18:30:02
## 题意
把用大括号括起来,逗号隔开的数转为 $16$ 进制(开头都有 `0x`),如果比 $10$ 进制表示的字符串长度短或等于,就输出 $16$ 进制的表示,否则输出 $10$ 进制的表示(放在大括号里)。
## 思路
这题一加入主题库就有很多人发讨论求助,看来大家不太擅长大括号的处理。所以本题解分成三部分来讲解:
### 一:大括号的处理
开头和结尾的大括号直接输出,每次读入一个 `char`,如果是数,就把它转 `int` 并加到数 $n$ 中,如果是逗号,**输出这个字符**并将 $n$ 转 $16$ 进制与十进制的长度对比。
然后我们能写出以下代码(`solve` 是转 $16$ 进制的函数):
```cpp
char c;
cin>>c;
cout<<c;
int n=0;
char a;
cin>>a;
if(a=='}'){solve(n);cout<<a;return 0;}
else if(a!=','){n=n*10+((int)a-48);goto be;}
else{solve(n);cout<<a;n=0;goto be;}
```
即使 $16$ 进制转换写对,这个主函数只有 $80$ 分,为什么?
看向样例 $2$:
in:`{}`
out:`{0}`
ans:`{}`
我们会发现,要对读入的字符串特判:直接读入一对空大括号时直接输出!
code for main:
```cpp
char c;
cin>>c;
cout<<c;
int n=0,f=0;
if(0){//除了 goto,永不进入此 if 语句
be:
f=1;
}
char a;
cin>>a;
if(a=='}'){if(!f){return cout<<a,0;}solve(n);cout<<a;return 0;}
else if(a!=','){n=n*10+((int)a-48);goto be;}
else{solve(n);cout<<a;n=0;goto be;}
```
### 二:转进制的处理
像数位分离一般的处理,每次模 $16$,这一位数小于等于 $10$ 就正常处理到字符串中,否则用 `A` 此类字母处理到字符串中。
核心处理:
```cpp
while(a>0){
y=a%16;
if(y<10) s=char('0'+y)+s;
else s=char('A'-10+y)+s;
a=a/16;
}
```
比较字符串长度只要将处理好的字符串开头补 `0x` 并与 `main` 处理好的 $n$ 转字符串比长度即可。
code for solve:
```cpp
int y=0;
string s="";
string st=to_string(a);//C++11 的函数,将 int 转为 string 类
if(a==0){
cout<<0;
return;
}//数是 0 是必须特判!
while(a>0){
y=a%16;
if(y<10) s=char('0'+y)+s;
else s=char('A'-10+y)+s;
a=a/16;
}
s="0x"+s;
if(st.length()>=s.length()) cout<<s;
else cout<<st;
```
### 三:一些特殊的注意点
这题是需要 `unsigned long long` 的!处理数字时,因为 `unsined`,所以无需管负数的情况。
## 整体代码
```cpp
#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
void solve(int a){
int y=0;
string s="";
string st=to_string(a);
if(a==0){
cout<<0;
return;
}
while(a>0){
y=a%16;
if(y<10) s=char('0'+y)+s;
else s=char('A'-10+y)+s;
a=a/16;
}
s="0x"+s;
if(st.length()>=s.length()) cout<<s;
else cout<<st;
}
signed main(){
char c;
cin>>c;
cout<<c;
int n=0,f=0;
if(0){
be:
f=1;
}
char a;
cin>>a;
if(a=='}'){if(!f){return cout<<a,0;}solve(n);cout<<a;return 0;}
else if(a!=','){n=n*10+((int)a-48);goto be;}
else{solve(n);cout<<a;n=0;goto be;}
}
```
[AC 记录](https://www.luogu.com.cn/record/68650641)
Add:在比赛中加上了快读,卡进了 $17$ ms,需要的也可以参照:<https://www.luogu.com.cn/record/68616414>