2019年9月PAT - 练习笔记——3.6
以下页码标注的是阅读器中实际页码,而不是书本身自印的页码。
第3章 入门篇(1)——入门模拟
3.6 字符串处理
注意
- 字符的限定范围,见B1014/A1061
目录
- B1006 换个格式输出整数
- B1021 个位数统计
- B1031 查验身份证
- B1002 写出这个数
- B1009 说反话
- B1014/A1061 福尔摩斯的约会
- B1024/A1073 科学计数法
- B1048 数字加密
- A1001 A+B Format
- A1005 Spell It Right
- A1035 Password
- A1077 Kuchiguse
- A1082 Read Number in Chinese
-
B1006 换个格式输出整数
让我们用字母
B
来表示“百”、字母S
表示“十”,用12...n
来表示不为零的个位数字n
(<10),换个格式来输出任一个不超过 3 位的正整数。例如234
应该被输出为BBSSS1234
,因为它有 2 个“百”、3 个“十”、以及个位的 4。输入格式:
每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。
输出格式:
每个测试用例的输出占一行,用规定的格式输出 n。
输入样例 1:
234
输出样例 1:
BBSSS1234
输入样例 2:
23
输出样例 2:
SS123
-
我的
#include <iostream> using namespace std; int main(void) { int num = 0; cin >> num; for (int i = num / 100;i;--i) cout << "B"; for (int i = (num % 100) / 10;i;--i) cout << "S"; for (int i = 1;i <= num % 10;++i) cout << i; return 0; }
-
《算法笔记》P66
-
-
B1021 个位数统计
给定一个 k 位整数 N=dk−110k−1+⋯+d1101+d0 (0≤*di*≤9, i=0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以
D:M
的格式在一行中输出该位数字D
及其在 N 中出现的次数M
。要求按D
的升序输出。输入样例:
100311
输出样例:
0:2 1:3 3:1
-
我的
#include <iostream> #include <string> using namespace std; int main(void) { string n = ""; cin >> n; int number[10] = {0}; for (int i = 0;i < n.size();++i) ++number[n[i] - '0']; for (int i = 0;i < 10;++i) { if (number[i]) cout << i << ":" << number[i] << endl; } return 0; }
注意N是不超过1000位,别看成N≤1000
-
《算法笔记》P68
-
-
B1031 查验身份证
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:
首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值
Z
;最后按照以下关系对应Z
值与校验码M
的值:Z:0 1 2 3 4 5 6 7 8 9 10 M:1 0 X 9 8 7 6 5 4 3 2
现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。
输入格式:
输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。
输出格式:
按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出
All passed
。输入样例1:
4 320124198808240056 12010X198901011234 110108196711301866 37070419881216001X
输出样例1:
12010X198901011234 110108196711301866 37070419881216001X
输入样例2:
2 320124198808240056 110108196711301862
输出样例2:
All passed
-
我的
#include <iostream> #include <string> using namespace std; const int WEIGHT[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; const int MOD = 11; const char M[] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; int main(void) { int n = 0; cin >> n; bool flag = true; for (int i = 0;i < n;++i) { string ID = ""; cin >> ID; int sum = 0; for (int j = 0;j < 17;++j) { if (ID[j] == 'X') sum += 10 * WEIGHT[j]; else sum += (ID[j] - 48) * WEIGHT[j]; } if (ID[17] != M[sum % MOD]) { flag = false; cout << ID << endl; } } if (flag) cout << "All passed"; return 0; }
-
《算法笔记》P69
“只要前17位中存在非整数,就应当认为该身份证号有误,……”(即出现字母)
-
-
-
B1002 写出这个数
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
输入格式:
每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10100。
输出格式:
在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。
输入样例:
1234567890987654321123456789
输出样例:
yi san wu
-
我的
#include <iostream> #include <string> #include <stack> #include <vector> using namespace std; vector<string> mp = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; int main(void) { string n = ""; cin >> n; int sum = 0; for (int i = 0;i < n.size();++i) sum += n[i] - 48; if (!sum) cout << "ling"; else { stack<string> pinyin; for (;sum;sum /= 10) pinyin.push(mp[sum % 10]); cout << pinyin.top(); for (pinyin.pop();!pinyin.empty();pinyin.pop()) cout << " " << pinyin.top(); } return 0; }
-
《算法笔记》P71
-
-
B1009 说反话
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。
输出格式:
每个测试用例的输出占一行,输出倒序后的句子。
输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello
-
我的
#include <iostream> #include <string> #include <stack> using namespace std; int main(void) { stack<string>words; char *str = (char *)malloc(80); while (scanf("%s", str) != EOF) words.push(str); cout << str; for(words.pop();!words.empty();words.pop()) cout << " " << words.top(); free(str); return 0; }
-
《算法笔记》P72
-
-
B1014/A1061 福尔摩斯的约会
大侦探福尔摩斯接到一张奇怪的字条:
我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm
。大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04
,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母D
,代表星期四;第 2 对相同的字符是E
,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母A
到N
表示);后面两字符串第 1 对相同的英文字母s
出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。输入格式:
输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。
输出格式:
在一行中输出约会的时间,格式为
DAY HH:MM
,其中DAY
是某星期的 3 字符缩写,即MON
表示星期一,TUE
表示星期二,WED
表示星期三,THU
表示星期四,FRI
表示星期五,SAT
表示星期六,SUN
表示星期日。题目输入保证每个测试存在唯一解。输入样例:
3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm
输出样例:
THU 14:04
-
我的
#include <iostream> #include <string> using namespace std; const string WEEKDAY[] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; int main(void) { string str1 = "", str2 = ""; cin >> str1 >> str2; bool flagWeek = true; for (int i = 0;i < str1.size() && i < str2.size();++i) { if (str1[i] == str2[i]) { if (!flagWeek) { if ('0' <= str1[i] && str1[i] <= '9') { cout << 0 << str1[i] << ":"; break; } else if ('A' <= str1[i] && str1[i] <= 'N') { cout << to_string(str1[i] - 'A' + 10) << ":"; break; } } if (flagWeek && 'A' <= str1[i] && str1[i] <= 'G') { flagWeek = false; cout << WEEKDAY[str1[i] - 'A'] << " "; } } } cin >> str1 >> str2; for (int i = 0;i < str1.size() && i < str2.size();++i) { if (str1[i] == str2[i] && 'A' <= toupper(str1[i]) && toupper(str1[i]) <= 'Z') { printf("%02d", i); break; } } return 0; }
-
《算法笔记》P74
“步骤1和步骤2中不能出现A ~ Z,而是需要限定完整,即A ~ G或者A ~ N,否则会“答案错误””
-
-
B1024/A1073 科学计数法
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [±][1-9]
.
[0-9]+E[±][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。
输入格式:
每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。
输出格式:
对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。
输入样例 1:
+1.23400E-03
输出样例 1:
0.00123400
输入样例 2:
-1.2E+10
输出样例 2:
-12000000000
-
我的
#include <iostream> #include <string> using namespace std; int main(void) { string str = ""; cin >> str; if (str[0] == '-') cout << "-"; int pose = str.find('E'); int ee = 0; for (int i = pose + 2;i < str.size();++i) ee = ee * 10 + str[i] - '0'; if (str[pose + 1] == '-') { cout << "0."; for (int i = 0;i < ee - 1;++i) cout << 0; cout << str[1]; for (int i = 3;i < pose;++i) cout << str[i]; } else { cout << str[1]; if (ee > pose - 3) { for (int i = 3;i < pose;++i) cout << str[i]; for (int i = ee - pose + 3;i;--i) cout << 0; } else { int i = 0; for (;i < ee;++i) cout << str[3 + i]; if (3 + i < pose) { cout << '.'; for (;3 + i < pose;++i) cout << str[3 + i]; } } } return 0; }
-
《算法笔记》P76
“……小数点正好在整个数的最右边,是不需要输出小数点的。”
-
-
B1048 数字加密
本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。
输入格式:
输入在一行中依次给出 A 和 B,均为不超过 100 位的正整数,其间以空格分隔。
输出格式:
在一行中输出加密后的结果。
输入样例:
1234567 368782971
输出样例:
3695Q8118
-
我的
#include <iostream> #include <string> using namespace std; const int MOD = 13; const char NUMBER[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'J', 'Q', 'K'}; int main(void) { string a = "", b = ""; cin >> a >> b; for (int i = a.size();i < b.size();++i) a = "0" + a; for (int i = b.size();i < a.size();++i) b = "0" + b; for (int j = 0;j < b.size();++j) { if (1 == (b.size() - j) % 2) cout << NUMBER[(b[j] - '0' + a[j] - '0') % MOD]; else { int number = b[j] - a[j]; if (number < 0) number += 10; cout << number; } } return 0; }
题目没有明说,结果字符串应该按两字符串最大长度求
-
《算法笔记》P79
参考代码用的是先反转a和b,求出结果字符串,再反转结果字符串的方法
-
-
A1001 A+B Format
Calculate a+b and output the sum in standard format – that is, the digits must be separated into groups of three by commas (unless there are less than four digits).
Input Specification:
Each input file contains one test case. Each case contains a pair of integers a and b where −106≤a,b≤106. The numbers are separated by a space.
Output Specification:
For each test case, you should output the sum of a and b in one line. The sum must be written in the standard format.
Sample Input:
-1000000 9
Sample Output:
-999,991
-
我的
#include <iostream> #include <string> using namespace std; int main(void) { int a = 0, b = 0; cin >> a >> b; int sum = a + b; if (sum < 0) cout << '-'; sum = abs(sum); if (!sum) { cout << 0; return 0; } string sums = ""; for (int count = 1;sum;sum /= 10, ++count) { if (4 == count) { count = 1; sums = "," + sums; } char c = sum % 10; sums = to_string(c) + sums; } cout << sums; return 0; }
-
《算法笔记》P81
if (sum >= 1000000) printf("%d,%03d,%03d",sum/1000000,sum%1000000/1000,sum%1000); else if (sum >= 1000) printf("%d,%03d",sum/1000,sum%1000); else printf("%d",sum);
-
-
A1005 Spell It Right
Given a non-negative integer N, your task is to compute the sum of all the digits of N, and output every digit of the sum in English.
Input Specification:
Each input file contains one test case. Each case occupies one line which contains an N (≤10100).
Output Specification:
For each test case, output in one line the digits of the sum in English words. There must be one space between two consecutive words, but no extra space at the end of a line.
Sample Input:
12345
Sample Output:
one five
-
我的
#include <iostream> #include <string> #include <stack> using namespace std; const string pinyin[] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; int main(void) { string n = ""; cin >> n; if (n == "0") { cout << "zero"; return 0; } int sum = 0; for (int i = 0;i < n.size();++i) sum += n[i] - '0'; stack<string>output; for (;sum;sum /= 10) output.push(pinyin[sum % 10]); cout << output.top(); for (output.pop();!output.empty();output.pop()) cout << " " << output.top(); return 0; }
-
《算法笔记》P82
“注意到N≤10100,而最大和为每位都是9的情况,即数位和最大会有100 x 9 = 900……”
“请仔细检查英文单词的拼写”
-
-
A1035 Password
To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem is that there are always some confusing passwords since it is hard to distinguish
1
(one) froml
(L
in lowercase), or0
(zero) fromO
(o
in uppercase). One solution is to replace1
(one) by@
,0
(zero) by%
,l
byL
, andO
byo
. Now it is your job to write a program to check the accounts generated by the judge, and to help the juge modify the confusing passwords.Input Specification:
Each input file contains one test case. Each case contains a positive integer N (≤1000), followed by N lines of accounts. Each account consists of a user name and a password, both are strings of no more than 10 characters with no space.
Output Specification:
For each test case, first print the number M of accounts that have been modified, then print in the following M lines the modified accounts info, that is, the user names and the corresponding modified passwords. The accounts must be printed in the same order as they are read in. If no account is modified, print in one line
There are N accounts and no account is modified
whereN
is the total number of accounts. However, ifN
is one, you must printThere is 1 account and no account is modified
instead.Sample Input 1:
3 Team000002 Rlsp0dfa Team000003 perfectpwd Team000001 R1spOdfa
Sample Output 1:
2 Team000002 RLsp%dfa Team000001 R@spodfa
Sample Input 2:
1 team110 abcdefg332
Sample Output 2:
There is 1 account and no account is modified
Sample Input 3:
2 team110 abcdefg222 team220 abcdefg333
Sample Output 3:
There are 2 accounts and no account is modified
-
我的
#include <iostream> #include <string> #include <vector> using namespace std; typedef struct { string id; string pw; }Account; int main(void) { int n = 0; cin >> n; vector<Account> accounts; for (int i = 0;i < n;++i) { string id = "", pw = ""; cin >> id >> pw; bool flag = false; for (int j = 0;j < pw.size();++j) { switch(pw[j]) { case '1': flag = true; pw[j] = '@'; break; case '0': flag = true; pw[j] = '%'; break; case 'l': flag = true; pw[j] = 'L'; break; case 'O': flag = true; pw[j] = 'o'; break; default: break; } } if (flag) { Account account = {id, pw}; accounts.push_back(account); } } if (!accounts.size()) { if (n > 1) cout << "There are " << n << " accounts and no account is modified"; else cout << "There is 1 account and no account is modified"; } else { cout << accounts.size(); for (int i = 0;i < accounts.size();++i) cout << "\n" << accounts[i].id << " " << accounts[i].pw; } return 0; }
-
《算法笔记》P85
-
-
A1077 Kuchiguse
The Japanese language is notorious for its sentence ending particles. Personal preference of such particles can be considered as a reflection of the speaker’s personality. Such a preference is called “Kuchiguse” and is often exaggerated artistically in Anime and Manga. For example, the artificial sentence ending particle “nyan~” is often used as a stereotype for characters with a cat-like personality:
- Itai nyan~ (It hurts, nyan~)
- Ninjin wa iyada nyan~ (I hate carrots, nyan~)
Now given a few lines spoken by the same character, can you find her Kuchiguse?
Input Specification:
Each input file contains one test case. For each case, the first line is an integer N (2≤N≤100). Following are N file lines of 0~256 (inclusive) characters in length, each representing a character’s spoken line. The spoken lines are case sensitive.
Output Specification:
For each test case, print in one line the kuchiguse of the character, i.e., the longest common suffix of all N lines. If there is no such suffix, write
nai
.Sample Input 1:
3 Itai nyan~ Ninjin wa iyadanyan~ uhhh nyan~
Sample Output 1:
nyan~
Sample Input 2:
3 Itai! Ninjinnwaiyada T_T T_T
Sample Output 2:
nai
-
我的
#include <iostream> #include <algorithm> #include <string> #include <vector> using namespace std; int main(void) { int n = 0; cin >> n; getchar(); string kuchiguse = ""; getline(cin, kuchiguse, '\n'); for (int i = 1;i < n;++i) { string str = ""; getline(cin, str, '\n'); string tmp = ""; for (int j = kuchiguse.size() - 1, k = str.size() - 1;j >= 0 && k >= 0 && kuchiguse[j] == str[k];--j, --k) tmp = str[k] + tmp; if (tmp == "") { kuchiguse = "nai"; break; } else kuchiguse = tmp; } cout << kuchiguse; return 0; }
-
《算法笔记》P88
-
A1082 Read Number in Chinese
Given an integer with no more than 9 digits, you are supposed to read it in the traditional Chinese way. Output
Fu
first if it is negative. For example, -123456789 is read asFu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
. Note: zero (ling
) must be handled correctly according to the Chinese tradition. For example, 100800 isyi Shi Wan ling ba Bai
.Input Specification:
Each input file contains one test case, which gives an integer with no more than 9 digits.
Output Specification:
For each test case, print in a line the Chinese way of reading the number. The characters are separated by a space and there must be no extra space at the end of the line.
Sample Input 1:
-123456789
Sample Output 1:
Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
Sample Input 2:
100800
Sample Output 2:
yi Shi Wan ling ba Bai
-
我的
上次做这道题做了好久,没什么好办法,就是一直试一直凑,这次试了一下还是没什么思路,直接看参考了
-
《算法笔记》P91
-
题意
按中文发音规则输出一个绝对值在9位以内的整数。需要明确如下规则:
- ==如果在数字的某节(例如个节、万节、亿节)中,某个非零位(该节的千位除外)的高位是0,那么需要在该非零位的发音前额外发音一个零。==例如,……
- 每节的末尾要视情况输出万或者亿(个节除外)
-
思路
-
步骤1:整体思路是将数字按字符串方式处理,并设置下标left和right来处理数字的每一个节(个节、万节、亿节)的输出,即令left指向当前需要输出的位,而right指向与left同节的个位
-
步骤2:在需要输出的某个节中,需要解决的问题是如何处理额外发音的零。事实上,可以直接采用规则1中的表述来设计如下的算法:
设置bool型变量flag表示当前是否存在累积的零。当输出left指向的位之前,先判断该位是否为0:如果为0,则令flag为true,表示存在累积的零;如果非0,则根据flag的值来判断是否需要输出额外的零。在这之后,就可以输出该位本身以及该位对应的位号(十、百、千)。而当整一小节处理完毕后,再输出万或者亿。
-
-
注意点
- 边界数据0的输出应该为“ling"。编者采用的处理方法是在步骤2判断当前位是否为0时增加判断当前位是否为首位,只有当前位不是首位且为0时才令flag为true(详见代码)。当然读者也可以采用在程序读入数据后直接特殊判断的方法进行输出。
- 让left和right指向一个节的首位可以采用如下方法:初始先令left = 0,即用left指向首位;而令right = len - 1,即用right指向末位,其中len表示字符串长度。之后不断让right减4,并控制left + 4不超过right,就可以得到第一个节。之后不断让left - 4,并控制left + 4不超过right,就可以得到第一个节。由于left在输出过程中自增至下一节的首位,因此只需要在当前节处理完毕后令right加4,即可让right指向下一个节的末位。
- 如果万节所有位都为0,那么就要注意不能输出多余的万。例如,800000008的输出应该是"ba Yi ling ba"而不是“ba Yi Wan ling ba"
#include <cstdio> #include <cstring> char num[10][5] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; char wei[5][5] = {"Shi", "Bai", "Qian", "Wan", "Yi"}; int main() { char str[15]; gets(str); int len = strlen(str); int left = 0, right = len - 1; if (str[0] == '-') { printf("Fu"); left++; } while (left + 4 <= right) right -= 4; while (left < len) { bool flag = false; bool isPrint = false; // isPrint==false表示该节没有输出过其中的位 while (left <= right) { if (left > 0 && str[left] == '0') flag = true; else { if (flag == true) { printf(" ling"); flag = false; } if (left > 0) printf(" "); printf ("%s", num[str[left] - '0']); isPrint = true; if (left != right) printf(" %s", wei[right - left - 1]); // 某节中除了个位外,都需要输出十百千 } left++; } if (isPrint == true && right != len - 1) printf(" %s", wei[(len - 1 - right) / 4 + 2]); // 只要不是个位,就输出万或亿 right += 4; } return 0; }
-
-