题目描述
最近在JLOI网上的一个流行游戏中,选手要回答很难的问题。假如在规定时间内不能回答,系统将给出1个提示,之后再依次给出第2,3个提示。出现在答案中的是字母和下列字符:
‘.’,’,’,’:’,’;’,’!’,’?’,’-‘和空格(空格不会在开头和结尾出现)
字母是指:小写字母’a’…’z’ 大写字母 ‘A’…’Z’,其中aeiouAEIOU是元音字母。
生成提示的规则:
第1个提示:简单的将所有字母换成’.’即可;
第2个提示:从第1个提示而来,将所有字母的个数求出,再将总个数除以三,得到的最接近商的自然数N,将第1个提示中的前N个字母显示;
第3个提示:从第2个提示而来,将剩下的元音字母显示。假如没有可显示的元音字母,则从第1个提示而来,即我们将前2/3的字母显示(同样如不能被3整除则取最接近的整数)。
输入输出格式
输入格式:
仅一行,给出问题,问题字符数最多不超过50
输出格式:
三行:按规则输出的三行提示
输入输出样例
输入样例#1:
Upomoc! Lpv s nm pkrl sv smglsnk.
输出样例#1:
……! … . .. …. .. ……..
Upomoc! Lp. . .. …. .. ……..
Upomoc! Lpv s nm pkrl s. ……..
题解
题意很好理解,但这道题实在太考细节了…
随便乱打的一个测试样例竟然帮我找到第八组测试样例过不去的原因??hhhh…
有个小地方忘写了导致第十组样例一直WA…
为各位dalao献上蒟蒻的代码,详情请看注释。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using namespace std ;
string str1 ; //输入的原始串
string str2 ; //根据第1个提示之后的串
string str3 ; //将第2个提示之后的串复制到str3中
//string str4 ; str4 ? 并没有 str4,由str3或str2与str1可直接得出最后一个提示的串
int tot_alpha ; //统计总共的字母数字
bool check = false ; //检查第3个提示中是否有可显示的元音字母
int indexx ; //找到第2个提示第N个字母的位置
int closest(double a , double b , double c){ //在第二个提示中比较谁更接近,也可如上面几位dalao的round函数
if ( fabs(c - a) > fabs(c - b) ){ //比较浮点数绝对值,谁小谁更接近
return b ;
}
return a ;
}
void display_one(){ //提示1,直接处理字符串
str2 = str1 ;
for ( int i = 0 ; i < str1.size() ; i ++ ){
if ( isalpha(str2[i]) ){
str2[i] = '.' ;
tot_alpha ++ ;
}
}
cout << str2 << endl ;
return ;
}
void display_two(){ //提示2,由str1和str2组合而成
double number = tot_alpha / 3.0 ;
/*天花板ceil(element) 和 地板函数floor(element) (雾
ceil()向上取整,返回不小于element的最大的整数,
floor()向下取整,返回不大于element的最小的整数
*/
int num = closest(ceil(number) , floor(number) , number) ; //找到离商最接近的自然数N
int count_ = 0 ; //记录到目前出现的字母个数
for ( int i = 0 ; i < str1.size() ; i ++ ){
str3[i] = str1[i] ; //将串复制到str3,便于第三个提示的处理 *ps:之前觉得这个str3会用到,但写到后面发现没什么用...于是一直WA第十组样例的噩梦开始了...
/*纪念找到这个BUG的此组胡乱敲打的样例....
input: asd132asd123zxc
output: ...132...123...
output: asd132...123...
output: as.132a..123... 正确输出-> output: asd132a..123...
所以有了之后的 “用不着str3” 的疯狂打脸...
*/
if ( isalpha(str1[i]) ){ //ctype.h 头文件判断字符是否是字母函数
cout << str1[i] ; //输出原串str1中的对应字符
count_ ++ ; //若真字母个数+1
}else {
cout << str1[i] ; //输出原串str1中的对应字符
}
if ( count_ == num ) { //当字母个数等于N时,记录下标,并跳出
indexx = i ; //记录第N个字母的位置
break ;
}
}
for ( int i = indexx + 1 ; i < str1.size() ; i ++ ){ //输出str2之后的串
str3[i] = str2[i] ;
cout << str2[i] ;
}
cout << endl ;
return ;
}
void display_thr(){
/*str3 = str1 ;
此处若加上这语句会出现一个未知的错误..
如果有dalao知道为什么请告诉我,感激不尽!
*/
for ( int i = indexx + 1 ; i < str1.size() ; i ++ ){
/*
cytpe.h头文件 tolower() 函数将一个字母转换成小写字母,与之对应的是 toupper()
此处统一转成小写字母,便于处理大写元音字母与小写元音字母
*/
if ( tolower(str1[i]) == 'a' || tolower(str1[i]) == 'e' || tolower(str1[i]) == 'i' || tolower(str1[i]) == 'o' || tolower(str1[i]) == 'u' ){
check = true ; //说明有可显示的元音字母
}
}
if ( check ){ //若真,则由原串str1和str3组合生成答案
for ( int i = 0 ; i < indexx ; i ++ ){ //输出到第N个字母的位置
cout << str1[i] ;
}
for ( int i = indexx ; i < str1.size() ; i ++ ){
/*输出第N个字母之后的字符,并判断是否有元音字母,
若有则输出str1中的字母,若无则输出str3中的字符
*/
if ( tolower(str1[i]) == 'a' || tolower(str1[i]) == 'e' || tolower(str1[i]) == 'i' || tolower(str1[i]) == 'o' || tolower(str1[i]) == 'u' ){
cout << str1[i] ;
}else{
cout << str3[i] ;
}
}
}else{ //若非真,则由原串str1与str2组合生成答案
double number = tot_alpha / 3.0 * 2.0 ;
int count_ = 0 ;
int num = closest(ceil(number) , floor(number) , number) ;
for ( int i = 0 ; i < str1.size() ; i ++ ){
if ( count_ < num ){ //显示前2/3个字母
if ( isalpha(str1[i]) ){
cout << str1[i] ;
count_ ++ ;
}else{
cout << str1[i] ;
}
}
else{ //若字母个数等于num则输出str2之后的串
cout << str2[i] ;
}
}
}
return ;
}
int main(){
getline(cin , str1) ;
str3 = str1 ; //若不加上此句在 codeblocks 下会返回非零...如果有dalao知道是什么原因请告诉我,感激不尽!
display_one() ;
display_two() ;
display_thr() ;
return 0 ;
}