CSP-J2021第一轮C++试题第二道阅读题详解

源代码:

#include <iostream>
#include <string>
using namespace std;
char base[64];
char table[256];
void init()
{
    for (int i = 0; i < 26; i++) base[i] = 'A' + i;
    for (int i = 0; i < 26; i++) base[26 + i] = 'a' + i;
    for (int i = 0; i < 26; i++) base[52 + i] = '0' + i;
    base[62] = '+', base[63] = '/';
    for (int i = 0; i < 256; i++) table[i] = 0xff;
    for (int i = 0; i < 64; i++) table[base[i]] = i;
    table['='] = 0;
}
string decode(string str)
{
    string ret;
    int i;
    for (i = 0; i < str.size(); i += 4)
    {
        ret += table[str[i]] << 2 | table[str[i + 1]] >> 4;
        if (str[i + 2] != '=')
            ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;
        if (str[i + 3] != '=')
            ret += table[str[i + 2]] << 6 | table[str[i + 3]];
    }
    return ret;
}
int main()
{
    init();
    cout << int(table[0]) << endl;
    string str;
    cin >> str;
    cout << decode(str) << endl;
    return 0;
}

题目1:

22.输出的第二行一定是由小写字母、大写字母、数字和“+”、“/”、“=”构成的 字符串。( )

A.正确 B.错误

答案:B

解析:很明显的送分题,推演输出时经常会发现会输出其他字符。

题目2:

23.可能存在输入不同,但输出的第二行相同的情形。( )

A.正确 B.错误

答案:A

解析:送分题2号,1与2第二行输出相同。

题目3:

24.输出的第一行为 “-1”。()

A.正确 B.错误

答案:A

解析:送分题3号,永远是-1,不信你试试。

题目4:

25.设输入字符串长度为n, decode函数的时间复杂度为()

A.O(√n) B.O(n) C.O(nlogn) D.O(n^2)

答案:B

解析:稍微有点难。对时间复杂度不是很了解的小伙伴可以看看这个人写的博客:C++算法篇 算法时间复杂度图解_流年llyz的博客-CSDN博客_c++ 时间复杂度

(从这道题开始详解)

回到题目。文中for循环的代码是for (i = 0; i < str.size(); i += 4)。也就是说,当字符串长度为n时,可以知道时间复杂度为O(n/4)。当然,这不是最简形式!我们把系数1/4去掉,得到答案为O(n)。

题目5:

26.当输入为“Y3Nx”时,输出的第二行为()。

A.csp B.csq C.CSP D.Csp

答案:B

解析:算术题。同样对位运算不了解的小伙伴可以看看这个人写的博客,这里不过多讲解:位运算(&、|、^、~、>>、<<)_咋么又饿了的博客-CSDN博客_位运算<<

 我们再次回到题目。输入为"Y3Nx",长度为4,刚好够decode()的for()循环执行一次。从 "ret += table[str[i]] << 2 | table[str[i + 1]] >> 4;"开始计算。我们知道table[str[0]]=24,得出二进制码为00011000,然后左移两位,得到01100000。然后table[str[1]] = 55,得出二进制码为00110111,然后右移4位,得到00000011。执行"|"最终得到01100011,十进制为99,此时rex='c'。"str[2]!='0'"成立,执行"ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;",table[str[i + 1]] = 55,二进制是00110111,0x0f是00001111,执行"&"得到00000111,左移4位得到01110000。table[str[2]]==13,二进制00001101,右移两位的结果00000011,最终结果01110011,十进制115,此时ret='cs'。"ret += table[str[i + 2]] << 6 | table[str[i + 3]];"中table[str[2]]==13,二进制为00001101,左移6位得01000000。table[str[i + 3]]=49,二进制为00110001,最终得01110001,十进制113,得到ret='csq'。

题目6:

27.当输入为“Y2NmIDIwMjE=”时,输出的第二行为( )。

A.ccf2021 B.ccf2022 C.ccf 2021 D.ccf 2022

答案:C

解析:上面那道题的升级版,根据上面的过程重新做一遍。

这个字符串的长度是12,我们把它分成三段看'Y2Nm','lDlw','MjE='。我们可以看到,这个字符串的最后一个字符为'=',不满足"if (str[i + 3] != '=')"的条件,说明输出字符串长度为3*3-1,得8,排除A和B。接下来继续计算,我们可以看到,C,D选项区别在于'MjE='这一段的"ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2;"这1个输出上,所以我们只需要计算它就行了。table[str[i + 1]]=35,二进制为00100011,结果为00000011,向左4位后得00110000。table[str[i + 2]]=4,二进制为00000100,向右两位得00000001。最后按位或得00110001,十进制49,得到这一位为'1',所以答案是C。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值