b969. hello, everyone

學校教的程式語言課是用C,而C++我是自學,目前對於C++字串的使用還不是很熟練,所以想藉由這題熟悉一下用法。
getline(cin, string)可以讀取一整行含空白的string,而string.substr(a, b)這個函式則是從string中第a個字元開始擷取b個字元。
這題蠻簡單的,就是將第一行的輸入去掉空白,分別放入vector裡,然後直接輸出”第二行的內容, vec[i]”。

AC (2ms, 332KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<string>
#include<vector>
using namespace std;

int main(){
int i, pi=0, j;
string name, greet;
vector<string> vec;
getline(cin, name);
getline(cin, greet);
for(i=0;i<name.size();i++){
if(name[i]==' '){
vec.push_back(name.substr(pi,i-pi));
pi=i+1;
}
}
vec.push_back(name.substr(pi,name.size()));
for(i=0;i<vec.size();i++){
cout<<greet<<", "<<vec[i]<<endl;
}
return 0;
}

a009. 解碼器

做這題主要是想熟悉python操作字串的用法,在解題報告中有人只用一行就完成所有事情,而且是沒有用分號的情況下,真的是大佬,像我這樣的初學者只能縮到3行,而且也盡量讓每一行都做很多事。這次的解題步驟就用一行一行來講解。

第一行:用input()讀取一個string,ord(c)將該string的每個字元轉成ASCII碼,然後用original這個list儲存,一個字元的ASCII碼就是一個element。
第二行:讀取original,將裡面的每個元素的ASCII碼減7,並透過chr()轉成char,然後用after這個list儲存,一個字元就是一個element。
第三行:利用’’.join()這招將after轉成string並輸出。

AC (18ms, 3.3MB)

1
2
3
original = [ord(c) for c in input()]
after = [chr(c-7) for c in original]
print(''.join(after))

a022. 迴文

在Python裡,string的index還能有如此操作:

[A:B:C]
A指的是string的起始字元(不輸入則預設0)
B指的是string的結束字元(不輸入則預設為string的最後一個字元的位置)
C指的是字元取完後要往後幾格(不輸入則預設為1)
然後欄位C也能塞負整數,這樣得到的字元順序也是顛倒的。

註:list也能這樣操作

AC (20ms, 3.3MB)

1
2
3
s=input()
if s==s[::-1]:print('yes')
else:print('no')

a038. 數字翻轉

這是我原本的作法,讀到整數後,先判斷是不是0,然後再拆成一個一個的位數並放到list,最後將list倒著輸出。這個解法幾乎是最慢的解法,只差我沒有把list顛倒後合併成一個整數,然後輸出整數而已。不過如果今天我是用C或C++來解這題,我還真只能這樣解。

AC (17ms, 3.3MB)

1
2
3
4
5
6
7
8
n=int(input())
d=[]
if n==0:print('0')
else:
while n%10==0:n//=10
while n>0:
d.append(n%10);n//=10
for i in range(len(d)):print(d[i],end='')

看到python-94狂-2行解決,真的是簡單又粗暴。在input()後面加上[::-1],讓輸入的string直接變顛倒的。外面包住的int()再將這個顛倒的string變成整數,同時也解決最大為數為0的問題,一行就完成所有的事情。

AC (17ms, 3.3MB)

1
2
n=int(input()[::-1])
print(n)

b265. Q11286 - Conformity

其實我一直看不懂最受歡迎的「課程組合」的人數到底怎麼求出來的,我一開始以為是如果最多人的組合只有一個,就輸出那個人數,然後有超過一個組合最多人,就輸出有多少組,結果看完別人的code才知道原來是最多人數x符合的組合 ,怎麼想都怪怪的。

解完這題,爬了別人的code才發現,我可以直接輸入string,然後排序完就能拼起來了,我還多了一個整數轉成字串的動作。

AC (0.5s, 840KB)

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
#include<bits/stdc++.h>
using namespace std;

int main(){
int n,num[5],i,h;
while(cin >> n && n){
//建立一個map並記錄數量
map<string, int> cbList;

for(h=0;h<n;h++){
//輸入五個課程代號
for(i=0;i<5;i++){
cin >> num[i];
}

//排序完並拼成一個字串
sort(num, num+5);
string cb="";
for(i=0;i<5;i++){
cb += to_string(num[i]);
}

//有找到+1
if(cbList.count(cb)){
cbList[cb]++;
}

//沒找到就建立
else{
cbList[cb]=1;
}
}

int mx=0, ans=0;
//找出人數最多的組合
map<string, int>::iterator j;
for(j=cbList.begin(); j!=cbList.end(); j++){
if( (j->second) > mx ){
mx = j->second;
}
}

//看看共有多少組合一樣大
for(j=cbList.begin(); j!=cbList.end(); j++){
if( (j->second) == mx ){
ans += mx;
}
}

cout << ans << "\n";
}
return 0;
}

a308. NOIP2011 2.统计单词数

原本是打算讓start指向第一個字母,end指向最後一個字母,但想到測資可能會有雞巴的情況,比如兩個單字中間的空格不只一個,我就索性讓start,end都指向空白處。

AC (14ms, 4.2MB)

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
#include<bits/stdc++.h>
using namespace std;

int main(){
ios::sync_with_stdio(false);
string key, s;

//輸入
getline(cin, key);
getline(cin, s);
s = s + " ";

//全部轉小寫
int kl = key.size(), sl = s.size(), i;
for(i=0;i<kl;i++){
if('A' <= key[i] && key[i] <= 'Z'){key[i] += 32;}
}
for(i=0;i<sl;i++){
if('A' <= s[i] && s[i] <= 'Z'){s[i] += 32;}
}

//查找字串
int start = -1, end = 0, cnt = 0, first;
for(i=0;i<sl;i++){
//尋找空格
if(s[i] == ' '){
//標記結束點
end = i;

//比對長度是否和關鍵字相同
if(end-start-1 == kl){
int same = 1;
for(int jk=0,js=start+1 ; jk<kl ; jk++,js++){
if(key[jk] != s[js]){
same = 0;break;
}
}

if(same){
//還沒出現過
if(!cnt){first = start+1;}
cnt++;
}
}

//標記開始點
start = i;
}
}

//輸出結果
if(!cnt){cout << "-1\n";}
else{cout << cnt << " " << first << "\n";}
return 0;
}

a011: 00494 - Kindergarten Counting Game

以前只要是用C,或是C++處理字串,我都是馬上先宣告string,這次想挑戰不用string儲存完成這題,有點麻煩,因為還要多判斷換行符號,如果是用string做,只需要讀到EOF然後直接跳出來就好了,不過不宣告string這樣比較省記憶體,還是有好處的。

AC (2ms, 84KB)

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
#include<stdio.h>
#include<ctype.h>

int main(){
char c;
int cnt=0, rec=0;
while(scanf("%c",&c)!=EOF){
//遇到字母
if(isalpha(c)){rec=1;}

//遇到其他字元
else{
//如果這段文字有字母,就計入cnt。
if(rec){cnt++;rec=0;}
}

//遇到換行符號
if(c=='\n'){
printf("%d\n",cnt);
cnt=0;
}
}
if(cnt){printf("%d\n",cnt);}
return 0;
}

a221. 11734 - Big Number of Teams will Solve This

上面的b969也有遇到要去除空白的情況,這次我想換個方法,用stringstream。也順便弄了一個給C++的加速組合包。

AC (3ms, 356KB)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
speedup;
int t, i;
string team, judge;
cin >> t;
cin.ignore();
for(i=1;i<=t;i++){
getline(cin, team);
getline(cin, judge);
cout << "Case " << i << ": ";

// yes
if(team == judge){cout << "Yes\n";}
else{
// ofe
// get rid of space
stringstream ss;
string s, tmp="";
ss.clear(); // clear buffer
ss << team;
while(ss >> s){tmp += s;}
// check
if(tmp == judge){cout << "Output Format Error\n";}

// wa
else{cout << "Wrong Answer\n";}
}
}
return 0;
}

a466. 12289 - One-Two-Three

這題本來不打算放的,不過看到討論區某些人的思路,覺得還挺特別,就照著做了。

AC (23ms, 3.4MB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
n = int(input())
for i in range(n):
s = input()
a = 'one'

if len(s) != 3:
print(3) # 篩出三
else:
diff = 0
for j in range(3):
if s[j] != a[j]:
diff += 1
if diff > 1:
print(2) # 篩出二
else:
print(1) # 篩出一

a131. 00739 - Soundex Indexing

這題的輸出格式蠻難搞的,而且範例輸出的Column、|、__,根本不用輸出。

我的想法是用兩個變數x,y,x存這個字元的編碼,y存上一個字元的編碼,如果xy不一樣,而且x的值是在1~6之間,我們就放入num,當num都放滿了,直接跳出迴圈。

然後要注意一下範例測資裡的SCHAEFER,因為C跟S的編碼一樣,所以這個編碼2就不會被輸出。這就是為什麼我在初始化的時候先令y為第一個字母的編碼,然後跑迴圈就可以從第二個字母開始檢查。

AC (1ms, 72KB)

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
#include<stdio.h>
#include<string.h>

int code(char c){
switch(c){
case 'B': case 'P': case 'F': case 'V':
return 1;
case 'C': case 'S': case 'K': case 'G':
case 'J': case 'Q': case 'X': case 'Z':
return 2;
case 'D': case 'T':
return 3;
case 'L':
return 4;
case 'M': case 'N':
return 5;
case 'R':
return 6;
default :
return 0;
}
}

int main(){
char s[25];
puts(" NAME SOUNDEX CODE");
while(scanf("%s",s) != EOF){
int sl=strlen(s),i,num[3]={0},cnt=0,x,y=code(s[0]);

//算出編碼
for(i=1;i<sl;i++){
x = code(s[i]);
if(x!=y && x!=0){num[cnt]=x;cnt++;}
y = x;
if(cnt >= 3){break;}
}

//輸出
printf(" %-25s%c",s,s[0]);
for(i=0;i<3;i++){
printf("%d",num[i]);
}
printf("\n");
}
printf(" END OF OUTPUT");
return 0;
}

a467. 11398 - The Base-1 Number System

因為每筆輸入都會有空格,所以用getline讀整行字串,再用stringstream去掉空白並分割。分完後只需用長度來判斷該做什麼事即可。不過題目舉的例子11011我覺得不好,因為它是palindrome,這讓我搞錯進位的方向。舉1011為例,我以為是1x8 + 0x4 + 1x2 + 1x1,結果題目要的是1x8 + 1x4 + 0x2 + 1x1。

AC (38ms, 344KB)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
speedup;
string s,t;
while(getline(cin, s) && s != "~"){
int flag = 0, cnt = 0, i, ans = 0;

//轉成2進制
stringstream ss;
ss << s;
while(ss >> t && t != "#"){
int tl = t.length();
if(tl == 1){flag = 1;}
else if(tl == 2){flag = 0;}
else{
//轉成10進制
for(i=0;i<tl-2;i++){
ans = ans*2 + flag;
}
}
}

cout << ans << "\n";
}
return 0;
}

a520. 12416 - Excessive Space Remover

因為每一次操作都會影響所有的連續空白片段,所以我們只需要先得到最大的連續空白片段的長度,然後再算出要除以2幾次才會變一個空白,這個次數就是解答。

AC (2ms, 316KB)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
speedup;
string s;
while(getline(cin, s)){
int spl=0,mxspl=0,sl=s.length(),i;

//求出最大連續空白長度
for(i=0;i<sl;i++){
if(s[i] == ' '){spl++;}
else{
if(spl){
if(spl > mxspl){mxspl = spl;}
spl = 0;
}
}
}

//算出需多少次
int t=0,tmp;
while(mxspl > 1){
tmp = mxspl%2;
mxspl = mxspl/2 + tmp;
t++;
}

cout << t << "\n";
}
return 0;
}

a521. 12414 - Calculating Yuan Fen

這題我看到討論區告訴大家不要害怕TLE的時候,就先用C++躍躍欲試,結果我明明都幫IO端加速了,還是TLE。不知道是不是因為一直在string、stringstream、int之間做轉換很耗時。後來用C就只有用int array運算,速度真的快很多。

TLE (2s)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
speedup;
string s;
while(cin >> s){
int st=1,i,j,sl=s.length();
while(st <= 10000){
//將縮寫變成數字字串
stringstream ss;
string yf="";
for(i=0;i<sl;i++){
ss << s[i]-65+st;
}
yf = ss.str();

//相加看是否有緣分
int yl=yf.length(),t;
string tmp="";
for(i=0;i<yl-3;i++){
int yfl = yf.length();
for(j=0;j<yfl-1;j++){
t = yf[j] + yf[j+1] - 48;
if(t >= 58){t -= 10;}
tmp = tmp + (char)t;
}
yf = tmp;tmp = "";
cout << yf << "\n";
}

if(yf == "100"){
cout << st << "\n";
break;
}

st++;
}

if(st > 10000){
cout << ":(\n";
}
}
return 0;
}

AC (69ms, 96KB)

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
#include<stdio.h>
#include<string.h>

int main(){
char s[15];
while(scanf("%s",s) != EOF){
int st=1,i,j,sl=strlen(s);
while(st <= 10000){
//將縮寫變成數字字串
int ss[50],cnt=0,tmp;
for(i=sl-1;i>=0;i--){
tmp = s[i] - 65 + st;
while(tmp > 0){
ss[cnt] = tmp%10;
tmp /= 10;
cnt++;
}
}

//相加看是否有緣分
int cntt = cnt-3, cnto = cnt-1;
for(i=0;i<cntt;i++){
for(j=0;j<cnto;j++){
ss[j] = (ss[j] + ss[j+1]) % 10;
}
ss[j] = 0;
cnto--;
}

if(ss[0]==0 && ss[1]==0 && ss[2]==1){
printf("%d\n",st);
break;
}

st++;
}

if(st > 10000){
printf(":(\n");
}
}
return 0;
}

終於又有上榜的機會,而且還是第五名!
r5

a786. 8. 1337 XL8T0RZ

這題我是先用map儲存對照表,然後一次讀整行的1337文字,透過stringstream分割空白,再丟到對照表裡看能不能對照,如果可以就轉換輸出,如果找不到直接輸出本體。

AC (2ms, 336KB)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
map<string, string> dict;
string s,a,b,c;

cin >> s; //[L3X1K0N]

//先讀進並製作好對照表
while(getline(cin, s) && s!="[1337]"){
int sl = s.length(),i;
a="";b="";
for(i=0;s[i]!=':';i++){
a += s[i];
}
for(i+=1;i<sl;i++){
b += s[i];
}
dict[a] = b;
}

while(getline(cin, s) && s!="[3ND]"){
stringstream ss;
map<string, string>::iterator it;
ss << s;
//逐單字變換並輸出
while(ss >> c){
int find = 0;
for(it=dict.begin() ; it!=dict.end() ; it++){
if((it->first) == c){
cout << it->second;
find = 1;
break;
}
}
if(!find){cout << c;}
cout << " ";
}
cout << "\n";
}
return 0;
}

a787. 9. Mirror to the Stars

我的策略是遇到要水平翻轉的(R)直接用字串特性[::-1]將整行顛倒、遇到要垂直翻轉的(I)直接用迴圈特性從下往上輸出、遇到兩個全都要的(IR)就兩個特性一起用,python就是這麼爽。

AC (19ms, 3.4MB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try:
while 1:
a = input().split()
x = int(a[1])
y = int(a[2])
sky = [[0]*x for i in range(y)]
for i in range(y):
sky[i] = input()

print(a[0])
if a[3]=='R':
for i in range(y):
print(sky[i][::-1])
elif a[3]=='I':
for i in range(y-1,-1,-1):
print(sky[i])
elif a[3]=='IR':
for i in range(y-1,-1,-1):
print(sky[i][::-1])
except EOFError:
pass

c009. 10473 - Simple Base Conversion

恩,又學了一些stringstream的用法,這次還加入十六進位的轉換。也因為如果只轉hex,輸出的字母是小寫的,所以用setiosflags(ios::uppercase)把字母轉成大寫輸出。

AC (3ms, 344KB)

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
#include<bits/stdc++.h>
#define speedup ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;

int main(){
speedup;
string s;
while(cin>>s && s[0]!='-'){
stringstream ss;
string num="";
int n,sl=s.length(),i;
if(s[0]=='0'){
for(i=2;i<sl;i++){
num+=s[i];
}
ss<<num; //16進制的字串輸入ss
ss>>hex>>n; //輸出16進制的整數給n
cout<<dec<<n<<"\n"; //n轉成10進制輸出
}
else{
ss<<s; //10進制的字串輸入ss
ss>>n; //輸出10進制的整數給n
cout<<"0x";
cout << setiosflags(ios::uppercase) << hex << n << "\n"; //n轉成16進制輸出
}
}
return 0;
}

c060. 00392 - Polynomial Showdown

這題的輸出格式蠻難搞的,尤其是’ + ‘、’ - ‘,為了這個空白運算符,我多加了很多判斷式。

AC (1ms, 96KB)

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
#include<stdio.h>
#include<stdlib.h>

int main(){
int coe[9],i,first;
while(scanf("%d",&coe[0])!=EOF){
for(i=1;i<9;i++){scanf("%d",&coe[i]);}
int allZero=1,first=0;
for(i=0;i<9;i++){
if(coe[i]){allZero=0;break;}
}
if(allZero){
printf("0\n");
continue;
}
for(i=0;i<9;i++){
if(coe[i]){
//首項係數的前面不用印符號
if(first){
if(coe[i]>0){printf(" + ");}
else{printf(" - ");}
}
first++;

//印出係數
if(8-i>=1){
if(coe[i]==1){printf("x");}
else if(coe[i]==-1){
if(first>1){printf("x");}
else{printf("-x");}
}
else{
if(coe[i]>0){printf("%dx",coe[i]);}
else{
if(first>1){printf("%dx",coe[i]*-1);}
else{printf("%dx",coe[i]);}
}
}
}
else{
if(coe[i]>0){printf("%d",coe[i]);}
else{
if(first>1){printf("%d",coe[i]*-1);}
else{printf("%d",coe[i]);}
}
}

//印出次方
if(8-i > 1){printf("^%d",8-i);}
}
}
printf("\n");
}
}

封面圖源:Pixiv