1. 程式人生 > 其它 >LuoguP1617 愛與愁的一千個傷心的理由 題解

LuoguP1617 愛與愁的一千個傷心的理由 題解

LuoguP1617 愛與愁的一千個傷心的理由 題解

Update

  • \(\texttt{2020.9.13}\) 重新排版了一下此題解,刪掉了一些廢話。
  • \(\texttt{2020.9.18}\) 在題解一週年之際修改了 \(\texttt{Content}\) 部分中輸出打成輸入的小錯誤。
  • \(\texttt{2020.9.20}\) 改正了 \(\texttt{Update}\) 部分中 18 日打成 15 日的一個小錯誤。

Content

輸入一個數 \(n\),輸出它的英文讀法。

資料範圍:\(n\leqslant 9999\)

Solution

其實這道題目蠻簡單的,主要是注意一個細節。

Part 1 美式英語中 \(10000\) 以內的數的讀法

做這個題目讓我深感學好英語的重要性。所以,首先我們來講講題外話(其實也不算,畢竟這可是本題的核心),瞭解美式英語中 \(10000\)

以內的數的讀法,由此得出本題的做法。當然,如果你覺得我很囉嗦的話,也可以直接跳過本章(建議不跳過)。想跟我來的,下面,我們開始吧。

1.1 四位數

四位數,形如\(\overline{abcd}\)的數。關於它的讀法有以下幾個原則,這裡就以\(\overline{abcd}\)為例:(當然,\(a≠0\)

  1. 個十百位都是零,直接讀作\(\texttt{a thousand}\)(每單個數字的讀法總曉得吧QAQ)。

  2. 否則,如果兩位是零,有以下三種情況(因為\(C^2_3=3\)):

(1) 百、十位都是零,讀作\(\texttt{a thousand and d}\)

(2) 百、個位都是零

,讀作\(\texttt{a thousand c-ty}\)

注意:這裡的\(\texttt{c-ty}\)代表整十位數的讀法,例如\(20\)讀作\(\texttt{twenty}\)。特別注意!當\(\texttt{c-ty=10}\)的時候,前面要加\(\texttt{and}\)!以下若碰到這種情況,處理方法和這裡一樣!

(3) 個、十位都是零,讀作\(\texttt{a thousand b hundred}\)

  1. 否則,如果一位是零,也有三種情況(這個你們都知道的我就不說了QAQ):

(1) 百位是零,前兩位讀作\(\texttt{a thousand}\),後兩位的讀法有以下兩種情況:

一,後兩位數\(\geqslant11\)並且\(\leqslant19\) ,後兩按照11到19的讀法讀,具體如下:

\(11~eleven\)
\(12~twelve\)
\(13~thirteen\)
\(14~fourteen\)
\(15~fifteen\)
\(16~sixteen\)
\(17~seventeen\)
\(18~eighteen\)
\(19~nineteen\)

二,其他情況下,按照\(\texttt{c-ty d}\)\(\texttt{c-ty}\)已於上文解釋,此處不再重複。)的讀法讀。

(2)十位是零,讀作:\(\texttt{a thousand b hundred and d}\)

(3)個位是零,讀作:\(\texttt{a thousand b hundred c-ty}\)(注意後兩位是10的情況!上文已提,此處不提)。

  1. 那麼,其他的數的讀法是這樣子:\(\texttt{a thousand b hundred c-ty d}\)

1.2 三位數

三位數就比四位數簡單多了(當然,\(a=0,b≠0\)):

  1. 當有兩位是零時,本來有三種情況的,但那三種情況都會在二位數和一位數中會講,所以只有以下一種情況,大家稍安勿躁:

十、個位都是零,直接讀出\(\texttt{b hundred}\)

  1. 否則,當有一位是零時,有兩種情況:

(1)十位是零,讀作\(\texttt{b hundred and d}\)(注意\(\texttt{and}\)不能漏)。

(2)個位是零,讀作\(\texttt{b hundred (and) c-ty}\)(注意後兩位是10的情況)。

  1. 其他情況下,讀作\(\texttt{b hundred c-ty d}\)

1.3 兩位數

兩位數更簡單,直接總起來講吧。(當然,\(a=0,b=0,c≠0\)

如果個位是零,那麼讀作\(\texttt{c-ty}\)(這裡就不用考慮 \(10\) 了),否則讀作\(\texttt{c-ty d}\)

1.4 一位數

一位數。。。你只要記著諸如\(\texttt{one,two,three,etc.}\)這些單詞的拼寫就行。

Part 2 正解

由此我們可以發現,上面的這些其實就是這個程式的實現,四位數的最複雜,一位數的最簡單,但都要注意,不要犯諸如把\(\texttt{one,two,three,etc.}\)等這些單詞拼錯了,或者特判漏了,還有,這道題目最好要中間除錯,以便於看到你整個程式的執行過程(不過交上去的時候記得註釋掉)。

Code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;

const string num[11] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
const string ty[11] = {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
const string teen[21] = {"", "", "", "", "", "", "", "", "", "", "", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
int a[5], n, cnt;

int main() {
	scanf("%d", &n);
	int tmp = n;
	while(tmp) {
		a[++cnt] = tmp % 10;
		tmp /= 10;
	}
	int teens = a[2] * 10 + a[1];
//	for(int i = cnt; i >= 1; --i)	printf("%d ", a[i]);
//	puts("");
	if(cnt == 4) {
		cout << num[a[4]] << ' ';printf("thousand");
		if(a[1] == 0 && a[2] == 0 && a[3] == 0)
			return 0;
		else if(a[3] == 0 && a[2] && a[1]) {
			putchar(' ');
			if(teens >= 11 && teens <= 19) {
				cout << teen[teens];
				return 0;
			}
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << "and " << ty[a[2]];
			putchar(' ');
			cout << num[a[1]];
		} else if(a[3] && !a[2] && a[1]){
			putchar(' ');
			cout << num[a[3]];
			printf(" hundred and ");
			cout << num[a[1]];
		} else if(a[3] && a[2] && !a[1]) {
			putchar(' ');
			cout << num[a[3]];
			printf(" hundred ");
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << ty[a[2]];
		} else if(a[3] && !a[2] && !a[1]) {
			cout << ' ' << num[a[3]];
			printf(" hundred");
		}
		else if(!a[3] && a[2] && !a[1]) {
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << ty[a[2]];
		}
		else if(!a[3] && !a[2] && a[1])
			cout << " and " << num[a[1]];
		else {
			cout << ' ' << num[a[3]] << " hundred ";
			if(teens >= 11 && teens <= 19)
				cout << teen[teens];
			else {
				cout << ty[a[2]] << ' ' << num[a[1]];
			}
		}  
	} else if(cnt == 3) {
		cout << num[a[3]]; printf(" hundred");
		if(!a[2] && !a[1])	return 0;
		else if(a[2] && !a[1]) {
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << ty[a[2]];
		}
		else if(!a[2] && a[1]) {
			printf(" and ");
			cout << num[a[1]];
		} else if(teens < 11 || teens > 19) {
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << ty[a[2]];
			cout << ' ' << num[a[1]];
		} else
			cout << ' ' << teen[teens];
	} else if(cnt == 2) {
		if(teens >= 11 && teens <= 19)
			cout << teen[teens];
		else if(!a[1]) {
			if(a[2] == 1)	cout << " and " << ty[1];
			else	cout << ty[a[2]];
		}
		else
			cout << ty[a[2]] << ' ' << num[a[1]];
	} else
		cout << num[a[1]];
	return 0;
}