《C++编程这样学》第九章:字符数组和字符串- 加油站题解

1.单词的长度

题目链接:http://csp.magu.ltd/problem/J0960

【问题描述】

在一行中输入一行单词序列,相邻单词之间用1个或多个空格间隔,编写程序,计算各个单词的长度。
注意,如果一个单词中有标点符号(如连字符,逗号),标点符号算作与之相连的单词的一部分,没有被空格隔开的符号串,都算作单词。

【题解代码】
#include <iostream>
#include <cstring>
using namespace std;

char s[1010];

int main()
{
	cin.getline(s, 1010);
	int len = strlen(s);
	int cnt = 0;
	for (int i = 0; i < len; i ++)
	{
		if (s[i] != ' ') cnt ++;
		else {
			if (cnt != 0) cout << cnt << ",";
			cnt = 0;
		}
	}
	cout << cnt;
	return 0;
}

2.阿尔法乘法

题目链接:http://csp.magu.ltd/problem/J0961

【问题描述】

阿尔法星球的乘法(简称为阿尔法乘法)法则如下, A ∗ B A*B AB 等于一个取自A、一个取自B的所有数字对的乘积的和。
例如,数A是123,数B是45,则 A ∗ B A*B AB的结果为:

1 ∗ 4 + 1 ∗ 5 + 2 ∗ 4 + 2 ∗ 5 + 3 ∗ 4 + 3 ∗ 5 = 54 1*4+1*5+2*4+2*5+3*4+3*5=54 14+15+24+25+34+35=54

编写程序,输入数A和B,用阿尔法乘法法则计算A*B的值。

【题解代码】
#include <iostream>
#include <cstring>
using namespace std;

char a[1010], b[1010];

int main()
{
    cin >> a >> b;
    int n = strlen(a), m = strlen(b);
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            sum += (a[i] - '0') * (b[j] - '0');
        }
    }
    cout << sum;
    return 0;
}

3.字符串p型编码

题目链接:http://csp.magu.ltd/problem/J0962

【问题描述】

下面举例说明字符串p型编码串的规则为:

例如,字符串122344111可描述为1个1、2个2、1个3、2个4、3个1组成,因此我们说“122344111”的p型编码串为“1122132431”;类似地,p型编码串101可以用来描述“1111111111”;而“00000000000”由11个0组成,因此它的p型编码串即为“110”;“100200300”由1个1、2个 0、1个2、2个0、1个3、2个0组成,因此它的p型编码串为“112012201320”。

编写程序,输入一个完全由数字字符(‘0’,‘1’,‘2’,…,‘9’)组成的字符串,输出它的p型编码串。

【题解代码】
#include <iostream>
#include <cstring>
using namespace std;

char s[10010];

int main()
{
	cin >> s;
	int cnt = 1;
	int len = strlen(s);
	for (int i = 1; i < len; i ++) {
		if (s[i] == s[i-1]) cnt ++;
		else {
			cout << cnt << s[i-1];
			cnt = 1;
		}
	}
	cout << cnt << s[len-1];
	return 0;
}

4.字符串解压

题目链接:http://csp.magu.ltd/problem/J0963

【问题描述】

字符串压缩方法之一是把字符串连续的相同字母压缩为“长度+字母”的形式,但单个的字母不压缩。
例如:“aaabbbbbcccd”,压缩后是“3a5b3cd”,“abcdee”压缩后是“abcd2e”。

编写程序,输入压缩后的字符串,输出压缩前的字符串。

【题解代码】
#include <iostream>
#include <cctype> // isdigit
#include <string>
using namespace std;

int main()
{
    string s;
    cin >> s;
    int t = 1;
    for (int i = 0; i < s.size(); i++)
    {
        if (isdigit(s[i]))
        {
            t = s[i] - '0'; // '2' -> 2
        }
        else
        {
            while (t--)
            {
                cout << s[i];
            }
            t = 1; // cd
        }
    }
    return 0;
}

5.魔法项链

题目链接:http://csp.magu.ltd/problem/J0964

【问题描述】

国王收到一串魔法项链,这串魔法项链每天都可以分影为自己的两倍长或不变,例如原始长度为“AB”,第一次分影变为“ABBA”,第二次分影变为“ABBAABBA”,第三次分影变为“ABBAABBAABBAABBA”…,万变不离其宗,国王虽然已被迷惑,但聪明的你一眼就能看出项链的原始长度。

编写程序,根据给出的魔法项链字符串的状态,计算出它最初可能的最小长度。

【题解代码】
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
    string s;
    cin >> s;
    int n = s.size();
    int ans = 1;
    for (int i = 1; i <= n; i++)
    {
        string t = s.substr(0, i);
        while (t.size() < n)
        {
            string tmp = t;
            reverse(tmp.begin(), tmp.end());
            t += tmp;
        }
        if (t.size() == n && s == t)
        {
            cout << i << endl;
            break;
        }
    }
    return 0;
}

6.ISBN号码

题目链接:http://csp.magu.ltd/problem/J0965

【问题描述】

每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其格式如x-xxx-xxxxx-x,其中符号“-”就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符之后的三位数字代表出版社,例如670表示维京出版社;第二个分隔符后的五位数字表示该书在该出版社的编号;最后一位为识别码。

识别码的计算方法如下:

首位数字乘以1加上次位数字乘以2,加上第3位数字乘以3……以此类推,用所得的结果对11取模,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码 4 是这样得到的:对 067082162 这9个数字,从左至右,分别乘以1,2,…,9再求和,即 0 ∗ 1 + 6 ∗ 2 + … … + 2 ∗ 9 = 158 0*1+6*2+……+2*9=158 01+62+……+29=158,然后计算 158 % 11 158\%11 158%11,得到的结果4即为识别码。

编写程序,判断输入的ISBN号码中识别码是否正确,如果正确,则输出“Right”;如果错误,则输出你认为是正确的ISBN号码。

【题解代码】
#include <iostream>
#include <cstring>
using namespace std;

char s[20];
char node[] = "0123456789X";

int main()
{
    cin >> s;
    int n = strlen(s);
    int sum = 0, t = 1;
    for (int i = 0; i < n - 1; i++)
    {
        if (s[i] != '-')
        {
            sum += (s[i] - '0') * t;
            t++;
        }
    }
    char id = node[sum % 11];
    if (s[n - 1] == id)
    {
        puts("Right");
    }
    else
    {
        s[n - 1] = id;
        puts(s);
    }

    return 0;
}

7.自动阅卷

题目链接:http://csp.magu.ltd/problem/J0966

【问题描述】

老师通过扫描学生们的试卷,得到了n道题目对应的n条加减计算题对应的字符串,每个字符串一行,字符串形式如下:
A + B = C
A - B = C
A + B = ?
A - B = ?

其中A、B、C分别是加减法运算的第一数、第二个数和运算结果,'?'表示这个题学生不会计算,其中A、B都在0~1000之间。

编写程序,帮老师完成自动阅卷,统计有多少道题的答案是正确的。

【题解代码】
#include <iostream>
#include <cctype>
#include <string>
#include <algorithm>
using namespace std;

int main()
{
	int n, res = 0;
	cin >> n;
	while (n --)
	{
		string s;
		cin >> s;
		int a = 0, b = 0, ans = 0;
		int pos = 0;
		char op;
		while (pos < s.size() && isdigit(s[pos]))
		{
			a = a*10 + s[pos]-'0';
			pos ++;
		}
		op = s[pos];
		pos ++;
		while (pos < s.size() && s[pos] != '=')
		{
			b = b*10 + s[pos]-'0';
			pos ++;
		}
		pos ++;
		int t = 1;
		if (s[pos] == '-') {
			t = -1;
			pos ++;
		} 
		while (pos < s.size()) ans = ans*10+s[pos]-'0', pos ++;
		ans *= t;
		if (op == '+' && a+b==ans) res ++;
		if (op == '-' && a-b==ans) res ++;
	}
	cout << res << endl;
	return 0;
}

8.乒乓球

题目链接:http://csp.magu.ltd/problem/J0967

【问题描述】

国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。

比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分):WWWWWWWWWWWWWWWWWWWWWWLW

在11分制下,根据前11个字母可知,华华第一局以11比0获胜;根据第12到第22个字母可知,华华在第二局以11比0获胜,正在进行第三局,当前比分是1比1。而在21分制下,此时比赛结果是华华第一局以21比0获胜,正在进行第二局,当前比分是2比1。如果一局比赛刚开始,则此时比分为0比0。

编写程序,对于输入的一系列比赛结果信息(WL形式),输出正确的结果。

规则补充说明:在一局比赛中(以21分制为例),先得21分的一方为胜方,20平后,先多得2分的一方为胜方,如果20平后双方的比分一直只差一分,则一直比下去,直至有人先多得2分的为止。

【题解代码】
#include <iostream>
using namespace std;
char a[110000];
void work(int n)
{
    int w = 0, l = 0;
    for (int i = 1; a[i] != 'E'; i++)
    {
        if (a[i] == 'W')
            w++;
        else
            l++;
        if ((w >= n && w - l >= 2) || (l >= n && l - w >= 2))
        {
            cout << w << ':' << l << endl;
            w = 0;
            l = 0;
        }
    }
    cout << w << ':' << l;
    cout << endl;
}
int main()
{
    for (int i = 1; i; i++)
    {
        cin >> a[i];
        if (a[i] == 'E')
        {
            break;
        }
    }
    work(11);
    cout << endl;
    work(21);
    return 0;
}

9.潜伏者

题目链接:http://csp.magu.ltd/problem/J0968

【问题描述】

R国和S国陷入战火之中,双方都互派间谍潜入对方内部,伺机行动。历经艰险后,潜伏于S国的R国间谍小C终于摸清了S国军用密码的编码规则:

  1. S国军方内部对欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母A—Z构成(无空格等其他字母);
  2. S国对于每个字母规定了对应的“密字”。加密的方法就是将原信息中的所有字母替换为其对应的“密字”;
  3. 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”。“密字”可以和原字母相同。

例如,若规定‘A’的密字为‘A’,‘B’的密字为‘C’(其他字母及对应的密字略),则原信息“ABA”被加密为“ACA”。现在,小C通过内线掌握了S国网络上发送的一条加密信息及其对应的原信息。小C希望能通过它们,破译S国的军用密码。小C的破译过程是这样的:扫描原信息,对于原信息中的字母x(代表任一大写字母),找到其在加密后的信息中的对应字母y,并认为在密码里y是x的密字。如此进行下去直到停止于如下的某个状态:

  1. 全部信息扫描完毕,所有26个字母在原信息中均出现过并获得了相应的“密字”;
  2. 全部信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现;
  3. 扫描中发现原信息和加密后的信息有明显的矛盾或错误(违反S国密码的编码规则)。例如某条信息“XYZ”被翻译为“ABA”就违反了“不同字母对应不同密字”的规则。

在小C忙得头昏脑胀之际,R国司令部又发来电报,要求他翻译另外一条从S国刚刚截取的加密信息。现在请你帮助小C通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译刚刚截取的加密信息。

【题解代码】
#include <iostream>
#include <cstring> // memset(鏁扮粍鍚嶏紝濉厖鍊硷紝鍏冪礌澶у皬锛?
using namespace std;

const int N = 110;
char a[N], b[N], c[N];
int st[30];
int vis[30];

int main()
{
    cin >> a >> b >> c;
    int n = strlen(a);
    memset(st, -1, sizeof st);
    memset(vis, -1, sizeof vis);

    bool f = 1;
    for (int i = 0; i < n; i++)
    {
        int ida = a[i] - 'A';
        int idb = b[i] - 'A';
        if (st[ida] == -1 && vis[idb] == -1)
        {
            st[ida] = idb;
            vis[idb] = ida;
        }
        else if (st[ida] == idb && vis[idb] == ida)
        {
            continue;
        }
        else
        {
            f = 0;
            break;
        }
    }
    for (int i = 0; i < 26; i++)
    {
        if (st[i] == -1)
        {
            f = 0;
            break;
        }
    }
    if (f == 0)
    {
        cout << "Failed";
        return 0;
    }
    for (int i = 0; i < strlen(c); i++)
    {
        printf("%c", st[c[i] - 'A'] + 'A');
    }
    return 0;
}
  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值