P8115 题解

Jerrlee✅

2022-02-09 18:30:02

Solution

## 题意 把用大括号括起来,逗号隔开的数转为 $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>