Jerrlee's blog

Jerrlee's blog

(2Y /-\|< |0|!

P8115 题解

posted on 2022-02-09 18:30:02 | under 题解 |

题意

把用大括号括起来,逗号隔开的数转为 $16$ 进制(开头都有 0x),如果比 $10$ 进制表示的字符串长度短或等于,就输出 $16$ 进制的表示,否则输出 $10$ 进制的表示(放在大括号里)。

思路

这题一加入主题库就有很多人发讨论求助,看来大家不太擅长大括号的处理。所以本题解分成三部分来讲解:

一:大括号的处理

开头和结尾的大括号直接输出,每次读入一个 char,如果是数,就把它转 int 并加到数 $n$ 中,如果是逗号,输出这个字符并将 $n$ 转 $16$ 进制与十进制的长度对比。

然后我们能写出以下代码(solve 是转 $16$ 进制的函数):

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:

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 此类字母处理到字符串中。

核心处理:

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:

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,所以无需管负数的情况。

整体代码

#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 记录

Add:在比赛中加上了快读,卡进了 $17$ ms,需要的也可以参照:https://www.luogu.com.cn/record/68616414